stage0: more bugfixes, size improvements

This commit is contained in:
anna 2023-05-28 19:21:06 +02:00
parent 6886d43eef
commit cb7eb4ec22
Signed by: fef
GPG key ID: 2585C2DC6D79B485

View file

@ -224,10 +224,10 @@ GLOBL _start
push %ax /* save CRC[15:0] */ /* '1 v */
xor %si, %si
mov $0x5c, %cl
call crc32
call crc32 /* %ebx = ~CRC, CF = 1 */
pop %ax /* restore CRC[15:0] */ /* '1 ^ */
test %eax, %ebx
jnz err_bad_gpt_csum
adc %eax, %ebx /* check CRC and set %ebx = 0 if equal */
jne err_bad_gpt_csum
/* store everything we need to rember from the GPT header (we assert there
* to be no more than 65535 partitions and that each entry is no more than
@ -332,10 +332,10 @@ LOCAL start2
pop %cx /* restore table size in bytes */ /* '3 ^ */
push %si /* save entry count */ /* '3 v */
xor %si, %si
call crc32
call crc32 /* %ebx = ~CRC, CF = 1 */
pop %cx /* restore entry count */ /* '3 ^ */
pop %di /* restore CRC[15:0] */ /* '2 ^ */
and %ebx, %edi /* %edi = 0 (crc32 returns the inverted value) */
adc %ebx, %edi /* %edi = 0 if checksum matches */
jnz err_bad_gpt_csum
/*
@ -358,10 +358,18 @@ LOCAL start2
/*
* Step 6: Load stage1 to the beginning of low memory (0x0500)
*
* stage1 must not exceed 32 K because some BIOSes freak out when asked
* to load 64 K or more at once (which would cross a segment boundary).
* We take advantage of that fact by "hardcoding" the number of bytes to
* be loaded: We start with 64 K - 1 B, and divide that through the
* logical sector size. The result is a sector count that definitely
* spans at least 32 K unless we're dealing with 64 K sectors or larger,
* in which case we wouldn't have made it this far anyway.
*/
2: push %dx /* save drive number */ /* '1 v */
mov $0x8000, %ax
or $-1, %ax
xor %dx, %dx
divw (drive_params + 0x18) /* %ax = 0x8000 / sector size = sector count */
xchg %ax, %cx /* %cx = sector count (xchg saves 1 byte) */
@ -387,9 +395,9 @@ LOCAL start2
xor %eax, %eax
xchg %fs:0x04(%si), %eax /* offset 0x04: CRC (replace with 0) */
push %ax /* save CRC[15:0] (crc32 clobbers %al) */ /* '4 v */
call crc32
call crc32 /* %ebx = ~CRC, CF = 1 */
pop %ax /* restore CRC[15:0] */ /* '4 ^ */
xor %ebx, %eax /* check CRC and clear %eax */
adc %ebx, %eax /* check CRC */
jnz err_bad_stage1_csum
/*
@ -449,11 +457,13 @@ LOCAL read_lba
END read_lba
/*
* Do a CCITT32 ANSI CRC (polynomial 0x04c11db7) of %cx bytes at %fs:%si
* and return THE COMPLEMENT (i.e. bitwise NOT of the CRC) in %ebx.
* Calculate the CCITT32 ANSI CRC (polynomial 0x04c11db7) of %cx bytes
* at %fs:%si and return THE COMPLEMENT of the result in %ebx.
* Clobbers %al, %cx, and %si. Does not check for overflows (%si + %cx
* must be <= 0x10000). If %cx is 0, the size is 64 KiB (0x10000), in
* which case %si should also be 0 because of the missing wrap check.
* This also sets CF = 1 because that allows for comparing the CRC with
* the expected value through a single `adc` instruction.
*
* Stolen from "Hacker's Delight", second edition by Henry S. Warren, Jr.
* and painstakingly ported to x86 assembly with focus on minimum size.
@ -461,10 +471,11 @@ END read_lba
* optimizations.
*
* %al: clobber
* %ebx: return value (ATTENTION: COMPLEMENT of CRC)
* %ebx: return value
* %cx: byte count (clobber)
* %si: data (clobber)
* %fs: data segment
* CF = 1
*/
LOCAL crc32
/* this is expressed as an imm8 w/ sign extension */
@ -483,6 +494,7 @@ LOCAL crc32
loop 1b
stc
ret
END crc32