Booting from CD under FDD emulation

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
johnsa
Member
Member
Posts: 296
Joined: Mon Oct 15, 2007 3:04 pm

Booting from CD under FDD emulation

Post by johnsa »

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..
johnsa
Member
Member
Posts: 296
Joined: Mon Oct 15, 2007 3:04 pm

Re: Booting from CD under FDD emulation

Post by johnsa »

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?

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

User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Booting from CD under FDD emulation

Post by Brendan »

Hi,

I've got no idea what's wrong, but...
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
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).


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.
johnsa
Member
Member
Posts: 296
Joined: Mon Oct 15, 2007 3:04 pm

Re: Booting from CD under FDD emulation

Post by johnsa »

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:

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 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...
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Booting from CD under FDD emulation

Post by Brendan »

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
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.
johnsa
Member
Member
Posts: 296
Joined: Mon Oct 15, 2007 3:04 pm

Re: Booting from CD under FDD emulation

Post by johnsa »

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?
johnsa
Member
Member
Posts: 296
Joined: Mon Oct 15, 2007 3:04 pm

Re: Booting from CD under FDD emulation

Post by johnsa »

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?
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Booting from CD under FDD emulation

Post by Brendan »

Hi,
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 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: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?
The EBDA is usually below 0x000A0000 (e.g. from 0x00098000 to 0x000A0000) but it's size depends on a lot of things.

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).
johnsa wrote:I guess it could be the area i allocate to load the 32kb in initially rather than the final 2Mb destination?
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.


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.
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Re: Booting from CD under FDD emulation

Post by bewing »

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.
johnsa
Member
Member
Posts: 296
Joined: Mon Oct 15, 2007 3:04 pm

Re: Booting from CD under FDD emulation

Post by johnsa »

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...
johnsa
Member
Member
Posts: 296
Joined: Mon Oct 15, 2007 3:04 pm

Re: Booting from CD under FDD emulation

Post by johnsa »

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?
johnsa
Member
Member
Posts: 296
Joined: Mon Oct 15, 2007 3:04 pm

Re: Booting from CD under FDD emulation

Post by johnsa »

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 :)
johnsa
Member
Member
Posts: 296
Joined: Mon Oct 15, 2007 3:04 pm

Re: Booting from CD under FDD emulation

Post by johnsa »

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.. ?
johnsa
Member
Member
Posts: 296
Joined: Mon Oct 15, 2007 3:04 pm

Re: Booting from CD under FDD emulation

Post by johnsa »

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..
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Booting from CD under FDD emulation

Post by Brendan »

Hi,
johnsa 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!
Good :)
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..
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.

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.
Post Reply