The first obstacle--somehow, my BIOS lost the fact that it's supposed to boot from the USB before the main HDD. That was easy enough to fix. Now for explanations on the other, harder problems. Note that some of the solutions I came up may not be necessary since this issue is the cause of a lot of failed USB boots.
I want a boot sector image that I can 'dd' to the USB key. The Grub method requires that I copy the image to a specific directory in the USB, unmount the drive, run grub, set the root, and type out the command to write it. Too much effort. I stripped out most of stage1.S and added my own code to just write @xx@ where xx is the drive name. I placed it on the USB, but it didn't boot.
To make it boot, I added in .bytes corresponding to stuff the boot sector seems to need--partition table, magic numbers, BIOS sector. I did that. Of course, I still hadn't confirmed the USB drive was in the proper boot order, so it may not have been necessary.
But I finally did get it o run. Here is the code that shows me the drive number.
repeat:
movw $0x0001, %bx /* set page and FG color */
movb $0x0e, %ah /* int 0x10 Teletype output */
movb $0x40, %al /* '@' as a marker character */
int $0x10 /* print the '@' */
movb %dl, %al /* put drive in %al */
shrb $4, %al /* shift upper nibble to lower */
cmpb $9, %al /* compare to 9 */
js upperIsNum /* if %al is 9 or less, skip next command */
addb $7, %al /* %al is over nine--adjust to make it 'a-f' */
upperIsNum:
addb $0x30, %al /* adjust to make 0-9 '0'-'9' and 17-22 into 'A'-'F' */
movb $0x0e, %ah /* int 0x10 Teletype output */
int $0x10 /* print */
movb %dl, %al /* put drive in %al */
andb $0x0f, %al /* mask off upper nibble */
cmpb $9, %al /* compare to 9 */
js lowerIsNum /* if %al is 9 or less, skip next command */
addb $7, %al /* %al is over nine--adjust to make it 'a-f' */
lowerIsNum:
addb $0x30, %al /* adjust to make 0-9 '0'-'9' and 17-22 into 'A'-'F' */
movb $0x0e, %ah /* int 0x10 Teletype output */
int $0x10 /* print */
movb $0x40, %al /* '@' as a marker character */
movb $0x0e, %ah /* int 0x10 Teletype output */
int $0x10 /* print */
movb $0x0d, %al /* \r */
movb $0x0e, %ah /* int 0x10 Teletype output */
int $0x10 /* print */
movb $0x0a, %al /* \n */
movb $0x0e, %ah /* int 0x10 Teletype output */
int $0x10 /* print */
hlt /* halt */
jmp repeat /* repeat */
Allow me to make some observations. First, 'hlt' doesn't halt. Or perhaps it does but then causes a reset. Second, the cmpb operands are out of order because this is AT&T style assembly and not 'nasm' assembly and the operands are reversed. At least, I think, because the js should jump if the result is negative. Third, the int 0x10's are described in http://en.wikipedia.org/wiki/INT_10.
This was the hard part--getting this to work. Can I work essentially blind? I knew that once I got this to work properly, the next steps would be progressively easier.
The next job--use int 0x13 to read the drive parameters for all 256 drives. If the carry flag is clear upon return from int 0x13, then print out the drive number of number of heads. I did that and got the three I expected.
Then I wrote one that takes the drives that exist and tests for the CHS values. I'll provide the code for the section I wrote:
call PrintDriveParams
repeat:
call Home
jmp repeat
/* print a marker '.' */
movb $0x2e, %al
call PrintAlChar
/* print the drive */
movb %dl, %al
call PrintAlHex
/* print a marker '.' */
movb $0x2e, %al
call PrintAlChar
hlt
PrintAlChar:
pusha /* save all registers */
movw $0x0001, %bx /* set page and FG color */
movb $0x0e, %ah /* int 0x10 Teletype output */
int $0x10 /* print */
popa /* pop all registers */
ret /* return */
PrintAlHex:
pusha /* save all registers */
movb %al, %dl /* save %al */
movw $0x0001, %bx /* set page and FG color */
movb $0x0e, %ah /* int 0x10 Teletype output */
movb %dl, %al /* put drive in %al */
shrb $4, %al /* shift upper nibble to lower */
cmpb $10, %al /* compare to 10 */
js upperIsNum /* if %al is 9 or less, skip next command */
addb $7, %al /* %al is over nine--adjust to make it 'a-f' */
upperIsNum:
addb $0x30, %al /* adjust to make 0-9 '0'-'9' and 17-22 into 'A'-'F' */
int $0x10 /* print */
movb %dl, %al /* put drive in %al */
andb $0x0f, %al /* mask off upper nibble */
cmpb $10, %al /* compare to 10 */
js lowerIsNum /* if %al is 9 or less, skip next command */
addb $7, %al /* %al is over nine--adjust to make it 'a-f' */
lowerIsNum:
addb $0x30, %al /* adjust to make 0-9 '0'-'9' and 17-22 into 'A'-'F' */
int $0x10 /* print */
popa /* pop all registers */
ret /* return */
NewLine:
pusha /* save all registers */
movw $0x0001, %bx /* set page and FG color */
movb $0x0e, %ah /* int 0x10 Teletype output */
movb $0x0d, %al /* \r */
int $0x10 /* print */
movb $0x0a, %al /* \n */
int $0x10 /* print */
popa /* pop all registers */
ret /* return */
PrintDriveParams:
pusha /* save all registers */
movb $0x00, %cl /* cl = 0 (drive = 0) */
movb $0x3c, %al /* print '<' marker */ call PrintAlChar printHeadsLoop: movb $0x08, %ah /* int 0x13 Read Drive Parameters */ movb %cl, %dl /* dl = cl (dl = drive) */ pushw %cx int $0x13 movw %cx, %bx pop %cx jc notValidHead /* print drive number */ movb %cl, %al call PrintAlHex movb $0x3a, %al /* print space */ call PrintAlChar movb %dh, %al /* heads */ call PrintAlHex movb $0x20, %al /* print space */ call PrintAlChar movb %bh, %al /* cylinders and sectors */ call PrintAlHex movb %bl, %al call PrintAlHex call NewLine notValidHead: incb %cl /* inc cl (drive++) */ cmpb $0x00, %cl jnz printHeadsLoop /* next */ printHeadsDone: movb $0x3e, %al /* print '>' marker */
call PrintAlChar
popa /* pop all registers */
ret /* return */
Home:
pusha /* save all registers */
movw $0, %bx
movw $0, %dx
movb $2, %ah
int $0x10
popa /* pop all registers */
ret /* return */
The result was this:
<00: 08 F6F8
80: FE FEFF
81: FE 00FF
>
The drive geometry of my flash drive is: 255 heads, 31 cylinders, 63 sectors per track--max head of 254 (oxfe), cylinder of 30 (0x1e << 6 == 0x780), sector 63 (ox3f). So the CHS should look like FE 07BF.
So I don't trust any of those numbers. But CHS addressing is inferior to LBA addressing anyway. So, I need to see which drives are able to be addressed via LBA. I suspect all of them. Time to start using int 0x13 with %ah = 0x42. But that'll have to wait until tomorrow morning.
No comments:
Post a Comment