Booting from CD under FDD emulation
Booting from CD under FDD emulation
Hey,
Has anyone had any issues when booting from a real machine with CDROM under el-torito, FDD emulation like this:
The 1st stage loader loads fine, all good.. it loads the 2nd stage loader (16kb/32x512byte sectors) using legacy BIOS functions / LBA->CHS as it determines there is no 13h extension support on the booted drive.
We enter the 2nd stage loader and it runs along, loads another file of the disk (in this case a large image (compressed mind you) around 200kb).. once again the 2nd stage loader sets our drive access mode to legacy as extension check failed AND OR obtaining the drive params from bios 13h extensions failed. It uses the same read-sectors function to load the data which for stability sake under legacy/LBA->CHS mode does the following:
1.reset controller for booted drive
2.lba->chs
3.load 1 sector
4.if carry go to 1 (max 5 times)
5.loop to 1 for however many sectors to load
in this case nothing seems to crash, but the image file loads about 16kb and then the data loaded becomes corrupt .. as the data is RLE'd once it gets drawn it wonks out badly obviously...
This whole exact same code/process runs perfectly from USB-HDD boot, FDC, bochs/qemu both using hdd and fdd options... so it seems to only be CD now thats an issue on real h/w
ill post the load_sectors function if that helps..
Has anyone had any issues when booting from a real machine with CDROM under el-torito, FDD emulation like this:
The 1st stage loader loads fine, all good.. it loads the 2nd stage loader (16kb/32x512byte sectors) using legacy BIOS functions / LBA->CHS as it determines there is no 13h extension support on the booted drive.
We enter the 2nd stage loader and it runs along, loads another file of the disk (in this case a large image (compressed mind you) around 200kb).. once again the 2nd stage loader sets our drive access mode to legacy as extension check failed AND OR obtaining the drive params from bios 13h extensions failed. It uses the same read-sectors function to load the data which for stability sake under legacy/LBA->CHS mode does the following:
1.reset controller for booted drive
2.lba->chs
3.load 1 sector
4.if carry go to 1 (max 5 times)
5.loop to 1 for however many sectors to load
in this case nothing seems to crash, but the image file loads about 16kb and then the data loaded becomes corrupt .. as the data is RLE'd once it gets drawn it wonks out badly obviously...
This whole exact same code/process runs perfectly from USB-HDD boot, FDC, bochs/qemu both using hdd and fdd options... so it seems to only be CD now thats an issue on real h/w
ill post the load_sectors function if that helps..
Re: Booting from CD under FDD emulation
Here is the loader function... MODE is configured to be [0=CHS no int13h extensions or drive params info failed / 1=int 13h ext. present and info obtained ]
Anyone have any ideas?
Anyone have any ideas?
Code: Select all
;====================================================================================
; ES:EBX = load location.
; ECX = sector count (in 512byte).
; EAX = starting sector.
;====================================================================================
loadsectors:
sti
push edi
; Get the number of sectors to load.
push eax
push ebx
; Adjust for specified sector size.
xor eax,eax
mov ax,fs:[BOOT_DRIVE_SECTOR]
xor edx,edx
mov ebx,512
idiv ebx ; (Correct boot drive sector size / 512).. eax = what to divide sector count by.
mov ebx,eax
xor edx,edx
mov eax,ecx
idiv ebx ; Divide Sector Count.
mov ecx,eax ; ECX = New Sector Count.
pop ebx
pop eax
cmp byte ptr fs:[BOOT_DRIVE_MODE],1
jne short chs_loader
; Here we know we have int13h extensions, so we can do an LBA load.
mov di,5 ; Attempt load 5 times at worst.
lba_loader:
mov esi,offset disk_packet
mov dword ptr ds:[esi+12],0
mov dword ptr ds:[esi+8],eax ; Store Starting Sector.
mov byte ptr ds:[esi+2],cl ; Store Sector Count to disk_packet.
mov ax,es
mov word ptr ds:[esi+6],ax ; Store Segment to Load To.
mov eax,ebx
mov word ptr ds:[esi+4],ax ; Store Offset to Load To.
mov dl,fs:[BOOT_DRIVE_ID]
mov ax,4200h
int 13h
jnc short lbaloaddone
dec di
jnz short lba_loader
pop edi
mov si,offset gen_str_fail ; Retried 5 times and failed.
call bootfail
lbaloaddone:
pop edi
ret
; Reading from a CHS device, so we'll do LBA->CHS translation and read.
chs_loader:
mov di,5
readsect:
push eax
xor ax,ax
mov dl,fs:[BOOT_DRIVE_ID] ; Reset Boot Drive.
int 13h
pop eax
push eax
push ecx
;LBA->CHS Translation.
push ebx
xor dx,dx
div word ptr fs:[BOOT_DRIVE_SPT]
inc dx
mov cx,dx ;ecx=sector
xor dx,dx
div word ptr fs:[BOOT_DRIVE_HEADS]
mov bx,ax ;ebx=cyl / edx=head
and cl,00111111b
mov al,bh
and al,00000011b
shl al,6
or cl,al
mov ch,bl
mov dh,dl
pop ebx
mov ax,0201h
mov dl,fs:[BOOT_DRIVE_ID]
int 13h
pop ecx
pop eax
jnc short rsok
dec di
jnz short readsect
pop edi
mov si,offset gen_str_fail ; Retried 5 times and failed.
call bootfail
rsok:
xor edx,edx
mov dx,word ptr fs:[BOOT_DRIVE_SECTOR]
add ebx,edx ; Go to next load location.
inc eax ; Increment LBA Sector Number.
dec ecx ; Decrement Sector Read Loop.
jnz chs_loader
pop edi
ret
Re: Booting from CD under FDD emulation
Hi,
I've got no idea what's wrong, but...
Cheers,
Brendan
I've got no idea what's wrong, but...
There's no need to reset the drive for every sector (even for an actual floppy disk) - you should only reset the drive if there was an error. This shouldn't cause problems (only worse performance), but it might be enough to make a buggy BIOS worse (as BIOS manufacturers tend to test their code on Windows, which doesn't constantly reset the drive for no reason, so what you're doing may not have been tested by the BIOS manufacturer).johnsa wrote:1.reset controller for booted drive
2.lba->chs
3.load 1 sector
4.if carry go to 1 (max 5 times)
5.loop to 1 for however many sectors to load
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Re: Booting from CD under FDD emulation
I thought so, I actually had it only on error, but moved it just to see if would help.. i was suspecting that maybe the drive wasn't spinning up fast enough, but not causing the read to return a carry/fail.. so i thought the reset might help... but no luck, both ways around seem to have the same result (albeit slower this way).
Basically the code that loads the image file in does it in small pieces as follows:
So it basically takes a chunk of 64 sectors (32kb at a time) and moves it.. I didn't want to load more than 64kb at a time (due to the real-mode seg:ofs limit possibly on the bios call EVEN though i'm in unreal mode).
So i picked 32kb arbitrarily and loaded that much at a shot, then move it. This code works under all other boot configs.. so I don't think its the process... the image draws perfectly after this load, and even under the CD boot it draws the first part then the RLE obviously gafs out badly while trying to fill vid-mem...
Basically the code that loads the image file in does it in small pieces as follows:
Code: Select all
;--------------------------------------------------------------------------------
; Load Background Image.
; (849x512bytes).
;--------------------------------------------------------------------------------
mov cx,13
mov eax,33
mov edi,200000h
limg:
push cx
push eax
mov ax,8000h
mov es,ax
xor ebx,ebx
pop eax
push eax
mov ecx,64
push edi
call loadsectors
pop edi
xor eax,eax
mov es,ax
mov esi,80000h
mov ecx,(64*512)
cl00:
mov al,es:[esi]
mov es:[edi],al
inc esi
inc edi
dec ecx
jnz short cl00
pop eax
add eax,64
pop cx
dec cx
jnz short limg
push edi
mov ax,8000h
mov es,ax
xor ebx,ebx
mov ecx,64
mov eax,33+832
call loadsectors
xor eax,eax
mov es,ax
mov esi,80000h
mov ecx,(17*512)
pop edi
cl01:
mov al,es:[esi]
mov es:[edi],al
inc esi
inc edi
dec ecx
jnz short cl01
So i picked 32kb arbitrarily and loaded that much at a shot, then move it. This code works under all other boot configs.. so I don't think its the process... the image draws perfectly after this load, and even under the CD boot it draws the first part then the RLE obviously gafs out badly while trying to fill vid-mem...
Re: Booting from CD under FDD emulation
Hi,
The only other thing I can think of is, maybe you're trashing the EBDA. To emulate 512-byte sectors, AFAIK the BIOS loads a 2048-byte sector from CD into a buffer in the EBDA, then gives you 512-bytes from this buffer.
Note: "a32 es rep movsd" works...
Cheers,
Brendan
The only other thing I can think of is, maybe you're trashing the EBDA. To emulate 512-byte sectors, AFAIK the BIOS loads a 2048-byte sector from CD into a buffer in the EBDA, then gives you 512-bytes from this buffer.
Note: "a32 es rep movsd" works...
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Re: Booting from CD under FDD emulation
Yep, i'll probably switch it to rep movsd
Thats a good idea.. let me check that theory out...
currently I just load the data to the 2Mb mark, which might be working all the time under other boots because nothing depends on the EBDA.. Whats the best way to check for the EBDA location? (then i'll make sure i don't override it).. also for how big the ebda is? (unfortunately these loads happen before i do the whole e820 stuff and other mem detects (im not sure I could re organize it to be the other way.. plus i read somewhere that e820 doesn't report a lot of those areas as unavailable ranges - like the ebda).
I currently pick up the ebda location as:
mov ax,40h
mov es,ax
movxz eax,es:[0eh]
shl eax,4
.. not sure if this is correct.. it would assume that the ebda location is below 1Mb and is a segment addr. with 0 offset?
I guess it could be the area i allocate to load the 32kb in initially rather than the final 2Mb destination?
Thats a good idea.. let me check that theory out...
currently I just load the data to the 2Mb mark, which might be working all the time under other boots because nothing depends on the EBDA.. Whats the best way to check for the EBDA location? (then i'll make sure i don't override it).. also for how big the ebda is? (unfortunately these loads happen before i do the whole e820 stuff and other mem detects (im not sure I could re organize it to be the other way.. plus i read somewhere that e820 doesn't report a lot of those areas as unavailable ranges - like the ebda).
I currently pick up the ebda location as:
mov ax,40h
mov es,ax
movxz eax,es:[0eh]
shl eax,4
.. not sure if this is correct.. it would assume that the ebda location is below 1Mb and is a segment addr. with 0 offset?
I guess it could be the area i allocate to load the 32kb in initially rather than the final 2Mb destination?
Re: Booting from CD under FDD emulation
It seems to be at 9f000 on my real h/w and under the emulators accoring to my previous post method.. in which case i don't see how loading 32kb to 80000 would cause a problem?
Re: Booting from CD under FDD emulation
Hi,
Instead of caring where the EBDA is, it's probably better to use "Int 0x12" to find the amount of RAM that you can use starting at 0x00000000. Without using "Int 0x12" I wouldn't assume that RAM above 0x00080000 is usable; but I would consider RAM below 0x00080000 safe to use (mostly due to backward compatibility, dating back to when IBM XT came with 512 KiB of RAM).
Cheers,
Brendan
The size of the EBDA (in KiB) is meant to be stored in the first word of the EBDA, although I wouldn't rely on that. E820 should report the EBDA as "reserved", and shouldn't report the video display memory area above it (but should report ROMs as "reserved").johnsa wrote:Whats the best way to check for the EBDA location? (then i'll make sure i don't override it).. also for how big the ebda is? (unfortunately these loads happen before i do the whole e820 stuff and other mem detects (im not sure I could re organize it to be the other way.. plus i read somewhere that e820 doesn't report a lot of those areas as unavailable ranges - like the ebda).
The EBDA is usually below 0x000A0000 (e.g. from 0x00098000 to 0x000A0000) but it's size depends on a lot of things.johnsa wrote:I currently pick up the ebda location as:
mov ax,40h
mov es,ax
movxz eax,es:[0eh]
shl eax,4
.. not sure if this is correct.. it would assume that the ebda location is below 1Mb and is a segment addr. with 0 offset?
Instead of caring where the EBDA is, it's probably better to use "Int 0x12" to find the amount of RAM that you can use starting at 0x00000000. Without using "Int 0x12" I wouldn't assume that RAM above 0x00080000 is usable; but I would consider RAM below 0x00080000 safe to use (mostly due to backward compatibility, dating back to when IBM XT came with 512 KiB of RAM).
The area at 0x00200000 isn't a problem. The 32 KiB buffer at 0x00080000 might be a problem (but it's unlikely). I don't know where your stack is, or if you use any other areas of RAM for anything else.johnsa wrote:I guess it could be the area i allocate to load the 32kb in initially rather than the final 2Mb destination?
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Re: Booting from CD under FDD emulation
Is it safe to use bios INT calls in unreal mode? I have always been under the impression that the bios may modify ES or DS during the operation of any INT call -- so at the end of an INT, you don't know if that segment is in real or unreal mode anymore?
It seems like any other assumption is simply assuming "good ASM programming practices" on the part of the bios writers, which is a totally silly thing to assume.
It seems like any other assumption is simply assuming "good ASM programming practices" on the part of the bios writers, which is a totally silly thing to assume.
Re: Booting from CD under FDD emulation
I moved the load area from 80000h to 70000h which should be safe at 458,752... below 512kb, not near anything i'm using (nor was 80000h tbh).. well below the ebda.. my stack is just below the stage 2 loader.. so it basically starts at 7c00-16 ( little bit of a buffer between it and beginning of code ).
stage2 loader is 16kb from 7c00-bc00 ..
I leave everything in the real ivt/bda alone..
my boot config info is stored from 500h - 700h.. (things like drive no, mode, vesa support so on etc etc)...
kernel loader uses the same 70000h address to load chunks , then moves them to 1Mb..
gdt is at 10000h temporarily during bootloader, pml4 and other tables are at c000,d000,e000 respectively (also temp until kernel)...
thats it basically...
stage2 loader is 16kb from 7c00-bc00 ..
I leave everything in the real ivt/bda alone..
my boot config info is stored from 500h - 700h.. (things like drive no, mode, vesa support so on etc etc)...
kernel loader uses the same 70000h address to load chunks , then moves them to 1Mb..
gdt is at 10000h temporarily during bootloader, pml4 and other tables are at c000,d000,e000 respectively (also temp until kernel)...
thats it basically...
Re: Booting from CD under FDD emulation
it is safe to use bios ints from unreal mode, thats the whole point really.. the thing to remember with unreal mode, is that while in pmode you're setting the limit s on the selectors to 4gig, once you're back in real mode that information is hidden (but still works).. so no matter what you write to a seg reg back in real mode after will only affect its base/address.. not it's limit.. so you'll still be in unreal mode.
ok.. i just noticed something silly, when i boot off a real cd as we've been discussing, it actually reports to me that int 13h extensions are supported.. which i think is either where the problem lies (in my code there.. as i'd report back a 2kb sector size and adjust accordingly).. or it's lying and maybe i should add a special check, that if the drive is < 80h then ignore what it says about extensions and use old legacy chs->lba code instead?
ok.. i just noticed something silly, when i boot off a real cd as we've been discussing, it actually reports to me that int 13h extensions are supported.. which i think is either where the problem lies (in my code there.. as i'd report back a 2kb sector size and adjust accordingly).. or it's lying and maybe i should add a special check, that if the drive is < 80h then ignore what it says about extensions and use old legacy chs->lba code instead?
Re: Booting from CD under FDD emulation
scratch that.. it did it once.. now everything i boot the cd it says no int13 extensions.... so the same problem remains.. image seems to load about 2kbs worth of data from cd, and then garbage..
man i'm going through a lot of cds here
man i'm going through a lot of cds here
Re: Booting from CD under FDD emulation
the only thing i can think now... is the following
when i boot from a real FDD, the drive no is 0 (for example).. so my code basically does the following.. instead of using bios to get drive info, it hardcodes
the 512/80cyl/2heads .. and then probes the spt by trying all the options 36,18... for 2.88, 1.44 disk and so on.. this seems to work well for a real FDD.. but maybe when its a CD booted under fdd emulation (even though the drive no. is still 0) i should use 13h func 08 again..
question is... is that probing method still necessary? if not.. great i'll just ditch it and rely on the bios.. if it is.. how would i know the difference between
real FDD = 0, and emulated cd/usb = 0 for fdd.. ?
when i boot from a real FDD, the drive no is 0 (for example).. so my code basically does the following.. instead of using bios to get drive info, it hardcodes
the 512/80cyl/2heads .. and then probes the spt by trying all the options 36,18... for 2.88, 1.44 disk and so on.. this seems to work well for a real FDD.. but maybe when its a CD booted under fdd emulation (even though the drive no. is still 0) i should use 13h func 08 again..
question is... is that probing method still necessary? if not.. great i'll just ditch it and rely on the bios.. if it is.. how would i know the difference between
real FDD = 0, and emulated cd/usb = 0 for fdd.. ?
Re: Booting from CD under FDD emulation
well bobs your uncle.... haha... removing the probing, and using func 08h to get the spt/head/cyl values.. and now cd-fdd works!
so the only question that remains is... is the probing code even necessary at ALL? I know the old linux boot code did it.. but perhaps its antiquated and not needed..
so the only question that remains is... is the probing code even necessary at ALL? I know the old linux boot code did it.. but perhaps its antiquated and not needed..
Re: Booting from CD under FDD emulation
Hi,
Note: For floppy disks, I wouldn't attempt to use int13 extensions at all - it shouldn't be supported for real or emulated floppies, and if you've got code to use legacy CHS then you're not gaining much by attempting to use int13 extensions. If your code is meant for both floppies and hard disks then you could do "if(drive_number >= 0x80) { attempt_int13_extensions(); } else { useCHS() }" (but IMHO it's easier to have separate boot loaders - one for floppy, one for hard disk, one for "no emulation" CD, one for PXE/network, etc).
Cheers,
Brendan
Goodjohnsa wrote:well bobs your uncle.... haha... removing the probing, and using func 08h to get the spt/head/cyl values.. and now cd-fdd works!
Probing is needed if there's no simpler way to reliably figure out what format the disk is. This isn't the case here - you could easily put a "BIOS Parameter Block" in the first sector. If you know your boot sector is on the disk, then you know your boot sector includes a BPB. As an extra bonus, this would mean that Windows could reformat the floppy (without a BPB, Windows decides the disk is trashed and won't format it, which isn't much fun for Windows users), and it'd be faster.johnsa wrote:so the only question that remains is... is the probing code even necessary at ALL? I know the old linux boot code did it.. but perhaps its antiquated and not needed..
Note: For floppy disks, I wouldn't attempt to use int13 extensions at all - it shouldn't be supported for real or emulated floppies, and if you've got code to use legacy CHS then you're not gaining much by attempting to use int13 extensions. If your code is meant for both floppies and hard disks then you could do "if(drive_number >= 0x80) { attempt_int13_extensions(); } else { useCHS() }" (but IMHO it's easier to have separate boot loaders - one for floppy, one for hard disk, one for "no emulation" CD, one for PXE/network, etc).
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.