Page 1 of 1

Can't get a simplest BIOS bootloader to boot from USB

Posted: Fri Mar 15, 2019 4:48 pm
by VioletGiraffe
Hello, a noob's question here, but I've done research it couldn't find a solution.

I've followed one of the many tutorials to write a simplest bootloader that prints "hello, world" and then halts. It boots in Bochs emulator (compiled it with NASM on Windows). Now I want to boot on real hardware and I want to place it on a USB thumb drive since I don't have any floppies lying around. I tried physically putting my compiled bootloader into the very first sector of the un-formatted USB drive, no luck, fails to boot. So I go ahead, google this topic, read about MBR and that it's required for HDD devices. My USB is booted in HDD mode, and I think it's booted in legacy BIOS mode, not UEFI.
So I took the sample MBR from this fine article and turn it into "Hello, world":

Code: Select all

[bits 16]
[org 0x0600]
 
start:
  cli                         ; We do not want to be interrupted
  xor ax, ax                  ; 0 AX
  mov ds, ax                  ; Set Data Segment to 0
  mov es, ax                  ; Set Extra Segment to 0
  mov ss, ax                  ; Set Stack Segment to 0
  mov sp, ax                  ; Set Stack Pointer to 0
  .CopyLower:
    mov cx, 0x0100            ; 256 WORDs in MBR
    mov si, 0x7C00            ; Current MBR Address
    mov di, 0x0600            ; New MBR Address
    rep movsw                 ; Copy MBR
  jmp 0:LowStart              ; Jump to new Address
 
LowStart:
	sti                     ; Start interrupts
	mov si, msg             ; SI now points to our message
	mov ah, 0x0E            ; Indicate BIOS we're going to print chars
.loop	lodsb                   ; Loads SI into AL and increments SI [next char]
	or al, al               ; Checks if the end of the string
	jz halt                 ; Jump to halt if the end
	int 0x10                ; Otherwise, call interrupt for printing the char
	jmp .loop               ; Next iteration of the loop

halt:	hlt                     ; CPU command to halt the execution
msg:	db "Hello, World!", 0   ; Our actual message to print
 
times (218 - ($-$$)) nop      ; Pad for disk time stamp
 
DiskTimeStamp times 8 db 0    ; Disk Time Stamp
 
bootDrive db 0                ; Our Drive Number Variable
PToff dw 0                    ; Our Partition Table Entry Offset
 
times (0x1b4 - ($-$$)) nop    ; Pad For MBR Partition Table
 
UID times 10 db 0             ; Unique Disk ID
PT1 times 16 db 0             ; First Partition Entry
PT2 times 16 db 0             ; Second Partition Entry
PT3 times 16 db 0             ; Third Partition Entry
PT4 times 16 db 0             ; Fourth Partition Entry
 
dw 0xAA55                     ; Boot Signature
I compile it, again place it into the first sector of an unformatted drive, and still nothing. What am doing wrong, and how can I do it right? Preferably, I'd like to do it on Windows.

Re: Can't get a simplest BIOS bootloader to boot from USB

Posted: Fri Mar 15, 2019 5:59 pm
by azblue
The first thing that jumps out at me is you don't know what your direction flag is -- if it's set, then the rep movs instructions count DOWN rather than up. Put a "CLD" command before your rep movs to see of that's it.

Now, I keep reading about some weird things BIOSes do with USB sticks, and I'm wondering if your BIOS might load your MBR, check for a legit entry in the partition table, and, upon not seeing one, decide it's not bootable, at which point it looks for the next bootable device, never passing control to your MBR.

If that's what it's doing, Make a valid partition and put a VBR there -- go with basically the same code you have here but a different message (and the CLD) and see if that loads.

Re: Can't get a simplest BIOS bootloader to boot from USB

Posted: Fri Mar 15, 2019 6:02 pm
by BenLunt
This is the typical USB boot problem.

Have a look at the following post. It explains the issue.

viewtopic.php?f=1&t=33558

Ben
- http://www.fysnet.net/osdesign_book_series.htm

Re: Can't get a simplest BIOS bootloader to boot from USB

Posted: Sun Mar 17, 2019 3:34 pm
by VioletGiraffe
Thanks a lot for the replies!
The direction flag was not why it didn't work, but I should have definitely cleared it.
BenLunt wrote: Have a look at the following post. It explains the issue.
viewtopic.php?f=1&t=33558
I took the properly constructed partition table from there, pasted it in bootloader, and it immediately worked on my laptop. Should I expect more trouble with some other BIOSes? Do I need more complexity to ensure reliable booting?

Oh, and more question while I have your attention, if I may: why move bootloader code within memory lower (in this case, from 0x7C00 to 0x0600) before jumping to it? What's the point?

Re: Can't get a simplest BIOS bootloader to boot from USB

Posted: Sun Mar 17, 2019 5:02 pm
by BenLunt
VioletGiraffe wrote:I took the properly constructed partition table from there, pasted it in bootloader, and it immediately worked on my laptop. Should I expect more trouble with some other BIOSes? Do I need more complexity to ensure reliable booting?
If you follow the comments in that post, you should be okay. There are other comments in other posts/forums, but that one should be enough.
VioletGiraffe wrote:why move bootloader code within memory lower (in this case, from 0x7C00 to 0x0600) before jumping to it? What's the point?
If you plan to load another boot sector, say from your MBR, you will need to be out of the way first.

All boot sectors expect to be loaded to physical address 0x07C00, therefore, you must load it to that location. If you do not move out of the way first, when you call the BIOS to load the new code to 0x07C00, as soon as the BIOS returns to your code, it actually isn't your code anymore. It is the new code at that location.

Ben
- http://www.fysnet.net/osdesign_book_series.htm