Page 1 of 2
Running a Bootloader from USB
Posted: Fri Feb 06, 2015 3:20 pm
by MustLearn
Hi!
I made a simple bootloader that i wanted to boot from a pen drive. Everything is running perfectly and the message is being displayed fine when running it from Virtual Box but the problem starts when i try to boot it form the pen drive even after copying it into Sector 0 using -
Code: Select all
dd if=Simple.asm of=/dev/sdc bs=512 count=1
Whenever i boot it from the pen drive, there is a black screen with a flickering cursor on the second line, 2-3 pixels from the left.
I would really appreciate some help to figure out what exactly is going wrong
This is the simple asm code i'm using(Pasting it here in case anyone needs to see it)-
Code: Select all
BITS 16
ORG 0x7C00
jmp main
;Variables
LoadString db "Bootloader Starting",0
Print:
lodsb
cmp al,0
je Done
mov ah, 0eh
int 10h
jmp Print
Done:
ret
main:
MOV SI, LoadString
CALL Print
jmp $
TIMES 510 - ($ - $$) db 0
DW 0xAA55
I even checked if the .bin file was being copied correctly using the hex editor, like in the image-
Re: Running a Bootloader from USB
Posted: Fri Feb 06, 2015 3:48 pm
by Roman
You didn't set up the segments.
Re: Running a Bootloader from USB
Posted: Fri Feb 06, 2015 3:52 pm
by MustLearn
Thanks for the reply, i'll try that
But one thing though, why would it run on Virtual Box just fine, if setting up the segments was the issue?
Re: Running a Bootloader from USB
Posted: Fri Feb 06, 2015 4:15 pm
by Techel
It isn't defined what's in the registers (except dl, containing the bootdrive). In an emulator they are mostly just 0 or already set up, on real hardware it might be different.
Re: Running a Bootloader from USB
Posted: Fri Feb 06, 2015 5:20 pm
by MustLearn
You didn't set up the segments.
Thank you!
Adding segments solved the problem!! (Resulted in newer ones though
)
It isn't defined what's in the registers (except dl, containing the bootdrive). In an emulator they are mostly just 0 or already set up, on real hardware it might be different.
Ohhhhhh!! I became fixated on there being a problem with my copying cause it ran on Virtual Box -.-
Re: Running a Bootloader from USB
Posted: Sat Feb 07, 2015 12:44 am
by Muazzam
MustLearn wrote:
Code: Select all
dd if=Simple.asm of=/dev/sdc bs=512 count=1
How problem is solved if you are copying .asm file instead of binary file.
Re: Running a Bootloader from USB
Posted: Sat Feb 07, 2015 4:59 am
by MustLearn
How problem is solved if you are copying .asm file instead of binary file.
Oh yeah sorry about that
I typed that here instead of copy pasting it from the command terminal and wrote .asm instead of .bin
That was completely my bad
Re: Running a Bootloader from USB
Posted: Sat Feb 07, 2015 5:47 am
by Combuster
Code: Select all
LoadString db "Bootloader Starting",0
That assembly doesn't correspond to your hexdump.
Re: Running a Bootloader from USB
Posted: Sat Feb 07, 2015 5:52 am
by MustLearn
I like edited the string, after i took the screenshot
But just the string and nothing else, that couldn't be the problem though :O
Re: Running a Bootloader from USB
Posted: Sat Feb 07, 2015 8:06 am
by MustLearn
Okay soo after adding the segment registers, it still didn't work on my desktop.
I tried running it on my sisters laptop and it ran perfectly
It still won't run on my desktop but runs perfectly fine on my sister's laptop
. Can anyone tell me why that is?
Re: Running a Bootloader from USB
Posted: Sat Feb 07, 2015 8:18 am
by Techel
Did you set up SS and SP correctly?
Code: Select all
xor ax, ax ;fast way to set ax to 0
mov ss, ax
mov sp, 0x7C00 ;stack points to ss:sp -> 0000:7C00 (below you bootloader, since the stack grows down)
Re: Running a Bootloader from USB
Posted: Sat Feb 07, 2015 8:40 am
by johnsa
Booting from USB has a few other caveats to consider..
There is no "native" way to boot from a USB device, so the BIOS (in order to allow this) does one of two things usually:
1) Pretend the USB is a FDD (in which case you'll start with DL=00h) and you can use normal int13h functions to read further sectors from the emulated floppy.
2) Pretend the USB is an HDD (in which case you'll start with DL=80h+) at which point you may be able to use the extended int 13h functions for reading with lba or the standard chs ones.
Further more i've noticed that on some machines the BIOS actually verifies certain things about the boot sector:
1) On one machine the BIOS doesn't check for the 0xaa55 signature, another one does and won't boot without it.
2) On one machine the USB is effectively USB-FDD and all works as planned.
3) On another it works as USB-HDD and works as planned.
4) On yet another machine it's USB-HDD but my original loader wouldn't work because THIS BIOS tries to verify the partition table (obviously expecting an MBR being an HDD)
5) On newer machines the MBR has been replaced with a GPT and I suspect that this machine that gives me headaches is in fact trying to verify the structure of the GPT partition.. although I find it strange that the BIOS would make an assumption
like this as it effectively rules out using an OS on the machine which doesn't yet make use of GPT for partitions....
Basically.. the bottom line is getting something which boots reliably on a lot/most machines is challenging. There are also many little catches (most of which are probably obsolete these days) to deal with various bios bugs and incompatabilities like resetting the FDC parameter table, ensuring DX is saved across an int13h call for sector reads.. another one as well to consider when setting up the segments initially is that (and i'm not sure if this still applies today but doesn't hurt)
is that some BIOSes may load you to 0000:7c00 while another might use 07c0:0000 (seg:ofs).
So it's a good idea to make sure you standardise that on boot to conform with your ORG.
Re: Running a Bootloader from USB
Posted: Sat Feb 07, 2015 8:41 am
by MustLearn
Did you set up SS and SP correctly?
I think so, this is what i'm using now and sis it works on the laptop, im assuming i'm doing it correctly?-
Code: Select all
BITS 16
start:
mov ax, 07C0h ; Set up 4K stack space after this bootloader
add ax, 288 ; (4096 + 512) / 16 bytes per paragraph
mov ss, ax
mov sp, 4096
mov ax, 07C0h ; Set data segment to where we're loaded
mov ds, ax
mov si, msg
call move
jmp $
msg db 'Whatever!', 0
move:
mov ah, 0Eh
.print:
lodsb
cmp al,0
je .Done
int 10h
jmp .print
.Done:
ret
times 510-($-$$) db 0
dw 0xAA55
Re: Running a Bootloader from USB
Posted: Sat Feb 07, 2015 8:44 am
by MustLearn
Further more i've noticed that on some machines the BIOS actually verifies certain things about the boot sector:
1) On one machine the BIOS doesn't check for the 0xaa55 signature, another one does and won't boot without it.
2) On one machine the USB is effectively USB-FDD and all works as planned.
3) On another it works as USB-HDD and works as planned.
4) On yet another machine it's USB-HDD but my original loader wouldn't work because THIS BIOS tries to verify the partition table (obviously expecting an MBR being an HDD)
5) On newer machines the MBR has been replaced with a GPT and I suspect that this machine that gives me headaches is in fact trying to verify the structure of the GPT partition.. although I find it strange that the BIOS would make an assumption
like this as it effectively rules out using an OS on the machine which doesn't yet make use of GPT for partitions....
How can i tell which machine does what?
I thought all machines checked for the aa55 signature :O
Re: Running a Bootloader from USB
Posted: Sat Feb 07, 2015 8:45 am
by johnsa
Here is my minimal example (using fasm):
Code: Select all
USE16
offset equ
org 0h ; I prefer to use 07c0:0000 instead of 0000:7c000 because i can relocate the code to a different segment address without affecting offsets in the code.
start:
jmp short begin
; BPB ... some bioses will NOT boot a USB-FDD or even real FDD without this block here.. I also cheat a bit and re-use some of the entries as variables..
nop
OEM DB "VXOS "
m_sectorsize DW 512
Sectors_per_cluster DB 1
Reserved_sectors DW 1
Number_of_FATs DB 2
Root_entries DW 224
Total_sector_count DW 2880
Media_descriptor DB 0f0h
Sectors_per_FAT DW 9
m_spt DW 18
Heads DW 2
m_cylinders DD 80 ; was Hidden_Sectors 1
m_sectors DD 18 ; was Large_Sectors 2880
bsDriveNumber DB 0
Current_Head DB 0
bsExtBootSignature DB 29h
m_heads DD 2 ; was VolumeID.
bsVolumeLabel DB "VXOS "
bsFileSystem DB "VXL12 "
begin:
db 0eah
dw offset cs_correction, 07c0h ; Hard-coded long jump to force cs:ofs correction.
;--------------------------------------------------------------------------------
; Configure Stack and Segment Registers.
;--------------------------------------------------------------------------------
cs_correction:
cld ; Ensure the direction flag is clear.
cli ; Switch off interrupts while we setup the stack.
xor ax,ax ; Configure segment registers and stack.
mov ss,ax
mov es,ax
mov sp,(7c00h-16) ; Set stack just below boot loader (padding to be safe).
push cs
pop ds
mov [m_driveNo],dl ;store boot drive no.
jmp short $
db 509-($-start) DUP (0) ; Padding to ensure that boot-loader is exactly 512 bytes for fdd/hdd/emulated boot modes.
m_driveNo db ? ; BIOS Boot Drive Number [00h=first floppy / 80h=first fixed disk]. We store it here so it's at a fixed location to be read later.
bios_sig db 055h,0aah ; BIOS 512byte sector boot signature.