Hey all,
I've re-started working on a hobby os project recently, and just brushed the dust off my old 1 and 2 stage boot loader code.
In the 1st stage loader I'm just using int 13h/func=02 to load the sectors (8 of them starting at sector 2) for the 2nd stage loader.
The BIOS call returns with no carry or errors, but the memory that it's written to es:bx is all 0's... any ideas?
It works under Bochs/VPC but this is booting it for real from my USB stick. The BIOS picks up the USB for boot perfectly and gets right thru all the 1st stage loader code.. (sees it as drive 80h).
I'm wondering if because it's seing it as a HDD I need to use 13h extensions? or perhaps i didn't reset the disk params table correctly.. is this necessary for HDD? (thought it was only for floppy).
Thanks!
John
Strange 1st stage boot loader issue
Re: Strange 1st stage boot loader issue
Hey all,
Just to update.. the idea with this boot-loader (stage1) is for it to be able to work from a floppy/hdd/cdrom or usb in a single unified way. From what I understand the BIOS emulates a HD when booting from usb or cdrom? the 2nd stage loader will always be under 16 sectors (8kb?) I'm assuming at boot time all devices would present 512 byte sectors (usb/hd/cd) via bios 13h 02h? - in which case i can avoid lba2chs or anything else in the stage1 loader.
I'm not worried about supporting partitions/mbr really for what i'm doing and i don't want to use a ready-made loader like grub etc seing as it's for fun and one might as well write it all to learn.
Here is the full code with regards to the previous post, perhaps someone can see a major flaw .. I've tried to combine what i've read and seen from various loaders to support FD/HD/USB ..
Any thoughts as to why this thing loads sectors for the 2nd stage with out any errors but the data is all just 0.
Just to update.. the idea with this boot-loader (stage1) is for it to be able to work from a floppy/hdd/cdrom or usb in a single unified way. From what I understand the BIOS emulates a HD when booting from usb or cdrom? the 2nd stage loader will always be under 16 sectors (8kb?) I'm assuming at boot time all devices would present 512 byte sectors (usb/hd/cd) via bios 13h 02h? - in which case i can avoid lba2chs or anything else in the stage1 loader.
I'm not worried about supporting partitions/mbr really for what i'm doing and i don't want to use a ready-made loader like grub etc seing as it's for fun and one might as well write it all to learn.
Here is the full code with regards to the previous post, perhaps someone can see a major flaw .. I've tried to combine what i've read and seen from various loaders to support FD/HD/USB ..
Any thoughts as to why this thing loads sectors for the 2nd stage with out any errors but the data is all just 0.
Code: Select all
.386p
code segment para public use16 'code'
assume cs:code, ds:code
;--------------------------------------------------------------------------------
; Ensure the assembler generates 0 relative offsets for our later CS correction.
; -> Some BIOSes will load the boot sector code to 0000:7c00 while others
; -> will load it to 07c0:0000. We move it to this in either event for
; -> simplicity and to ensure we can re-locate the code to a different segment
; -> without affecting the offsets.
;--------------------------------------------------------------------------------
org 0h
start:
jmp short begin ; This 2 byte jump will always be the first part of our MBR.
;-----------------------------------------------------------------------------------
; MDB (Master Disk Block) = 32bytes.
;-----------------------------------------------------------------------------------
m_filesystem db "VXFS" ; File System Type in Use on Logical Disk.
m_volume db "UNTITLED" ; Drive Volume Name.
m_heads dw 2 ; Heads per Disk (Physical).
m_cylinders dw 80 ; Cylinders Per Head (Physical).
m_sectors dd 18 ; Sectors Per Track (Physical).
m_sectorsize dw 512 ; Size in bytes of a sector (Physical).
m_driveNo db 00h ; 0 = fdd0 / 80h = hdd0.
m_mode dw 0 ; 1 = CHS / 0 = LBA.
m_first_sec dd 0 ; First Sector Of File System.
padding db 0
;###############################################################################################################
; BOOT LOADER CODE BEGINS HERE.
;###############################################################################################################
begin:
db 0eah ; Hard-coded long jump to seg:ofs as specified.
dw offset cs_correction, 07c0h
cs_correction:
cli ; Disable any interrupts.
xor ax,ax
mov es,ax
dec ax
mov sp,ax
mov ax,9000h
mov ss,ax ; Setup stack at 9000:ffff (common place).
mov ax,07c0h
mov ds,ax ; Ensure DS = CS (07c0:0000).
mov m_driveNo,dl ; Store the Boot Drive Number (BIOS will start us with this in DL).
xor si,si ; DS:SI = begin of original bootloader.
mov di,600h ; ES:DI = begin of new bootloader.
mov cx,100h ; Copy 256 words (512 bytes).
rep movsw ; Copy bootloader.
db 0eah ; Hardcode force far jmp.
dw offset bootloader_exc0,0060h ; new code addr = (0060:bootloader_exc0).
;=============================================================================================================
; Bootloader will commence from here at new address.
; -> All offsets need to be adjusted manually from here on due
; -> to self-modified execution address 600h.
; -> eg (offset Print_Msg-7c00h)+600h
; -> short IP relative jmps are fine.
; -> THIS IS NOW FIXED BY USING ORG 0h and seg:0000...!!!!
; -> Just out of interest 0600h happens to be the address DOS 1.x loaded to..
;=============================================================================================================
bootloader_exc0:
mov ax,060h ; Reset Seg Registers.
mov ds,ax ; CS and DS = 0060h.
;--------------------------------------------------------------------------------
; If we get this far, we can display the startup message and
; start doing some useful setup.
; -> Traditionally we'd want to check for a 386+ machine, but these days?
;--------------------------------------------------------------------------------
mov ax,03h ; Reset 80x25 text mode.
int 10h
mov si,offset msg0 ; Display Start Message.
call printstr
mov si,offset msg1 ; Display Boot Drive Number.
call printstr
mov al,m_driveNo
call printbyte
; The Interrupt Vector Table (IVT) occupies the first 1024 bytes of low memory and
; contains 256 4-byte entries. Each entry is an address to an Interrupt routine.
; The INT 1E vector (Diskette Configuration pointer) is at 0000:0078 and contains
; the address to the Diskette Parameter Table (DPT). (78h/4 = 1Eh)
;-----------------------------------------------------------------------------------
; -> Reset FDC Param Tables (apparently some BIOS have too low max sector
; count (7).. we need 36 for max 2.88 disks, this messes up multi-sector
; reads greater than the BIOS value. Too high is safe, too low not...
;-----------------------------------------------------------------------------------
push ds
mov bx,078h ; ES:BX = FDC BIOS Param Table Ptr.
lds si,es:[bx] ; DS:SI points to Param Table.
mov byte ptr ds:[si+4],36 ; Kludge Sector Per Track Count (36 = 2.88 disk). We try 63?
mov byte ptr ds:[si+9],0fh ; Reset Head Bounce Time.
pop ds ; Updates INT 1E table.
mov dl,m_driveNo
xor ax,ax
int 13h ; Reset Controller for booted drive.
;--------------------------------------------------------------------------------
; Did we get booted from a floppy, harddisk, usb or cdrom?
; -> USB will emulate a HDD boot (80h).
;--------------------------------------------------------------------------------
cmp m_driveNo,80h
jae skip_not_floppy
;====================================================================================
; FLOPPY DISK BOOT SOURCE.
;====================================================================================
mov m_heads,2 ; All floppies have 2 heads(?)
mov m_sectorsize,512 ; All floppies have 512 byte sectors.
mov m_cylinders,80 ; All floppies have 80 cylinders.
mov m_mode,1 ; All floppies have CHS addressing.
;-----------------------------------------------------------------------------------
; Probe Disk Drive Sectors per Track.
; -> Try 36, then 18 and so on to see what works as BIOS has no definite way
; -> of knowing using INT13H, SERVICE 08h... more arcane rubbish.
;-----------------------------------------------------------------------------------
mov ax,07c0h
mov es,ax
mov si,offset disksizes
probe_loop:
xor eax,eax
xor cx,cx
mov al,ds:[si]
inc si
cbw ; Extend AL to AX.
mov m_sectors,eax
cmp si,(offset disksizes)+4
jae short got_sect_size
mov cl,al
xor dx,dx
mov dl,m_driveNo
xor bx,bx ; Use future load address to overwrite (no danger).
mov ax,0201h
int 13h
jc short probe_loop ; If failed try next sector size down.
got_sect_size:
mov di,4 ; Retry load a few times.
readatt0:
xor ax,ax
mov dl,m_driveNo
int 13h ; Ensure FDC Boot Source is Reset Again.
mov ax,07c0h ; ES:[BX] = 07C0:0000
mov es,ax
xor bx,bx
mov ax,0208h ; Load 8 sectors.
mov dl,m_driveNo ; Drive to Load From (Boot Drive).
mov cx,02h ; Starting Sector
xor dh,dh
int 13h
jnc short doneloadingok
dec di
jnz short readatt0
mov si,offset errmsg1 ; Fail if we can't load stage2 loader.
call bootfail
doneloadingok:
mov dx,03f2h
xor al,al
out dx,al ; Ensure we turn off the floppy mode to enter 2nd stage loader in known state.
jmp doneloading
;====================================================================================
; HARD-DISK BOOT SOURCE.
;====================================================================================
skip_not_floppy:
mov ah,08h
mov dl,m_driveNo
int 13h
xor ax,ax
mov al,ch
mov ah,cl
and ah,11000000b
shr ah,6
mov m_cylinders,ax
xor eax,eax
mov al,cl
and al,00111111b
mov m_sectors,eax
mov ax,07c0h
mov es,ax
mov al,byte ptr es:[0]
call printbyte
mov di,4
attempthdload:
xor ax,ax
mov es,ax
mov dl,m_driveNo
int 13h
mov bx,07c00h
mov ax,0208h ; Load 8 sectors.
mov dl,m_driveNo ; Drive to Load From (Boot Drive).
mov cx,02h ; Starting Sector
xor dh,dh
int 13h
jnc short doneloading
dec di
jnz short attempthdload
mov si,offset errmsg1 ; Failed to load 2nd stage from HDD source.
call bootfail
;====================================================================================
; Switch to 2nd Stage Loader Now.
;====================================================================================
doneloading:
mov al,byte ptr es:[7c00h]
call printbyte
jmp short $
db 0eah
dw 0000h, 07c0h ; Hard coded Far Jump to 07c0:0000h.
;######################################################################################################
; !!!All first stage boot loader procedures and data go here!!!
;######################################################################################################
;Value Color Value Color
;00h Black 08h Dark gray
;01h Blue 09h Bright blue
;02h Green 0Ah Bright green
;03h Cyan 0Bh Bright cyan
;04h Red 0Ch Pink
;05h Magenta 0Dh Bright magenta
;06h Brown 0Eh Yellow
;07h Gray 0Fh White
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
; Print an ASCII string.
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
printstr:
mov ah,0Eh
mov bh,00h
mov bl,07h
lodsb
or al,al
jz short strDone
int 10h
jmp short printstr
strDone:
ret
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
; Print a byte value in hex.
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
printbyte:
pusha
xor ah,ah
mov cl,al
mov bh,00h
mov bl,07h
and al,11110000b
and cl,00001111b
shr al,4
mov si,offset hexLUT
add si,ax
mov al,ds:[si]
mov ah,0Eh
int 10h
xor ax,ax
mov al,cl
mov si,offset hexLUT
add si,ax
mov al,ds:[si]
mov ah,0Eh
int 10h
popa
ret
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
; Boot Failure and Reboot.
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
bootfail:
call printstr ; Display whichever error msg was passed in.
;mov si,offset errmsg0
;call printstr ; Display the "any key to reboot" message.
xor ax,ax
int 16h ; Wait for key press.
int 19h ; Force POST reboot by calling int 19h.
; ALTERNATIVE REBOOT.
; store magic value at 0040:0072h
; - 0000h - cold boot.
; - 1234h - warm boot.
;mov ax,40h
;mov es,ax
;mov word ptr es:[0072h],0000h
;db 0eah ; Jump to ffff:0000 (Alternative Reboot Scheme).
;dw 0000h
;dw 0ffffh
;=====================================================================================================
; BootLoader Data Area.
;=====================================================================================================
;errmsg0 db '<Press any key to reboot>',13,10,0
errmsg1 db 'error',13,10,0
msg0 db 'VXOS v1.0',13,10,0
msg1 db 'drive:',0
disksizes db 36, 18, 15, 9 ; SPT options for FDD. (Sectors per Track).
hexLUT db '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
db 510-($-start) DUP (0) ; Add padding to ensure boot loader code is exactly 512bytes long.
db 055h,0aah ; Boot loader signature which must be present at end of 512byte 1st sector.
; BIOS will check this magic number to ensure that it is a bootable sector.
code ends ; End of Code Segment.
end start ; End of Block Marker.
Re: Strange 1st stage boot loader issue
USB flash has the same structure as a hard disk therefore it does not need emulation in this aspect. Booting from CD-ROM can occur without emulation (with 2K sector size). In both cases boot loader must use EDD service.johnsa wrote:From what I understand the BIOS emulates a HD when booting from usb or cdrom?
If you have seen bad English in my words, tell me what's wrong, please.
Re: Strange 1st stage boot loader issue
Ok, so basically in the boot code I check to see if the drive no. is >= 80h... if not i assume floppy, do the manual spt probe and use int 15h 02 to load sectors.
If it's a HDD (this would indicate a real HDD, or USB in HDD emulation or possibly a CDROM? I've seen CDROM boot with driveno=0 as well?? large floppy emulation??)
In this case I'd use int 13h ah=42h to perform the sector reads with the relevant spt/heads info etc obtained from the 13h extension info?
Thanks!
If it's a HDD (this would indicate a real HDD, or USB in HDD emulation or possibly a CDROM? I've seen CDROM boot with driveno=0 as well?? large floppy emulation??)
In this case I'd use int 13h ah=42h to perform the sector reads with the relevant spt/heads info etc obtained from the 13h extension info?
Thanks!
Re: Strange 1st stage boot loader issue
Your understanding is slightly off. A bootable CDROM follows the El Torito standard. It allows for floppy emulation, hard disk emulation, or no emulation at all. For both floppy and hard disk emulation, the BIOS will translate sector sizes and fake drive geometry for your use. With no emulation, the BIOS will read 2048 byte sectors off the CD.johnsa wrote: Just to update.. the idea with this boot-loader (stage1) is for it to be able to work from a floppy/hdd/cdrom or usb in a single unified way. From what I understand the BIOS emulates a HD when booting from usb or cdrom? the 2nd stage loader will always be under 16 sectors (8kb?) I'm assuming at boot time all devices would present 512 byte sectors (usb/hd/cd) via bios 13h 02h? - in which case i can avoid lba2chs or anything else in the stage1 loader.
Booting from USB also has a bunch of standards to follow. There is USB-FDD, USB-HDD, and USB-ZIP. USB-FDD is a lot like a regular floppy. USB-HDD requires a partition table on the USB device. The device may have multiple partitions, and one of the partitions must be marked active. USB-ZIP requires a special geometry, as well as a partition table. However, it uses only one partition, and it must be the 4th entry in the partition table. Generally, these standards are incompatible, but it is possible (and quite tricky) to create a single bootloader that simultaneously complies with these three standards. I believe that USB-HDD is the most widely supported, however.
Re: Strange 1st stage boot loader issue
Ok, I'm with you.
So in terms of CD booting would it be safe to assume that most systems will implement a faked FDD/HDD boot thus resulting in the boot drive number being either 00h or 80h? If no emulation then what would the drive number be? Following then it would be imperative to obtain the bytes per sector info from either int 13/08 or 13/48h(assuming extensions are available) to load the stage2 loader from the CD and correctly handle 2kb sectors.
I think I could ignore USB-ZIP for now and just work from FDD/HDD again. I know that on my machine it emulates it as HDD (80h drive number on boot). Oddly though I don't have any partition table etc and the boot still works fine. Are you sure the Partition table is necessary? or is that more to fall in line with other standards like FAT etc?
Ignoring USB-ZIP should make it fairly trivial to get this working as a unified stage1 as the two emulations options will report drive number 0 or 80h and thus the two cases are handled seperately for
A) real floppy/usb-fdd/cd-rom as FDD
B) real hdd/usb-hdd/cd-rom as HDD
Following on I implemented the int13h extension read (42h) to see if that solved the problem i'm having off USB.. for all intense purposes the boot loader works and the usb stick boots, gets through 90% of the code and then only when loading the sectors up for the stage2 does it do this funny of not reporting an error bust just loading 0's... (it works in bochs/vmware).. but then again we all know how quirky "real" environments can be.
Needless to say it did not solve the problem, I even used the get disk info function to report back the geometry and obtained the following for:
Cyl: 1965
Heads: 1
SPT: 63
Sector-Size: 512
which to my mind = a 64Mb drive, and in truth the usb-stick is 1Gig.
I'm going to quickly burn this as iso onto a cd and see what happens when it boots that way.
So in terms of CD booting would it be safe to assume that most systems will implement a faked FDD/HDD boot thus resulting in the boot drive number being either 00h or 80h? If no emulation then what would the drive number be? Following then it would be imperative to obtain the bytes per sector info from either int 13/08 or 13/48h(assuming extensions are available) to load the stage2 loader from the CD and correctly handle 2kb sectors.
I think I could ignore USB-ZIP for now and just work from FDD/HDD again. I know that on my machine it emulates it as HDD (80h drive number on boot). Oddly though I don't have any partition table etc and the boot still works fine. Are you sure the Partition table is necessary? or is that more to fall in line with other standards like FAT etc?
Ignoring USB-ZIP should make it fairly trivial to get this working as a unified stage1 as the two emulations options will report drive number 0 or 80h and thus the two cases are handled seperately for
A) real floppy/usb-fdd/cd-rom as FDD
B) real hdd/usb-hdd/cd-rom as HDD
Following on I implemented the int13h extension read (42h) to see if that solved the problem i'm having off USB.. for all intense purposes the boot loader works and the usb stick boots, gets through 90% of the code and then only when loading the sectors up for the stage2 does it do this funny of not reporting an error bust just loading 0's... (it works in bochs/vmware).. but then again we all know how quirky "real" environments can be.
Needless to say it did not solve the problem, I even used the get disk info function to report back the geometry and obtained the following for:
Cyl: 1965
Heads: 1
SPT: 63
Sector-Size: 512
which to my mind = a 64Mb drive, and in truth the usb-stick is 1Gig.
I'm going to quickly burn this as iso onto a cd and see what happens when it boots that way.
Re: Strange 1st stage boot loader issue
Ok, I've tested it on FDD and CD-ROM under Bochs/VirtualBox/VMWare and on my real machine and all work. It's now only the USB thing that still seems strange.
I've include an attachment here with 3 things, the img file to write to a memory stick, an iso to burn to CD and a small utility I wrote a while ago to write/read sectors to devices called diskimage.
Usage:
To write 4,608 bytes to a USB drive (F:) use the following:
diskimage a.img 0 1200 \\.\F: 0
source and destination specify an offset and length.
If it's a physical device (a drive eg) then the offset is in sectors and length too.. if it's a file then it's in bytes.. both sets of values in hex.
If someone could test this for me using a USB stick they know boots that would be fantastic!
The correct output should be : EBFA ... which i get in all configs except USB where it's EB00 ... first byte is original value, 2nd is the first byte after the load.. FA is correct .. 00 not.
John
PS Feel free to use the little diskimage tool.
I've include an attachment here with 3 things, the img file to write to a memory stick, an iso to burn to CD and a small utility I wrote a while ago to write/read sectors to devices called diskimage.
Usage:
To write 4,608 bytes to a USB drive (F:) use the following:
diskimage a.img 0 1200 \\.\F: 0
source and destination specify an offset and length.
If it's a physical device (a drive eg) then the offset is in sectors and length too.. if it's a file then it's in bytes.. both sets of values in hex.
If someone could test this for me using a USB stick they know boots that would be fantastic!
The correct output should be : EBFA ... which i get in all configs except USB where it's EB00 ... first byte is original value, 2nd is the first byte after the load.. FA is correct .. 00 not.
John
PS Feel free to use the little diskimage tool.
- Attachments
-
- OStest.rar
- (6.95 KiB) Downloaded 76 times