flat assembler
Message board for the users of flat assembler.

Index > OS Construction > USB Booting Secrets

Author
Thread Post new topic Reply to topic
Mike Gonta



Joined: 26 Dec 2010
Posts: 243
Mike Gonta 31 Dec 2010, 18:54
Everything you always wanted to know about USB booting but were too USB (Unable or Sophisticated or Busy) to ask.

Have you ever seen this error message when trying to boot from a floppy disk?
Quote:
Remove disks or other media.
Press any key to restart
I guess that floppy is not bootable.
Or how about this message when booting from a CD?
Quote:
Boot from ATAPI CD-ROM :
Press any key to boot from CD. . .
If you don't touch the keyboard, that CD won't boot.
Or maybe you've seen this error message when booting from a USB flash drive?
Quote:
Disk error
Press any key to restart
Gee wiz, another boot failure, right? Wrong!

USB Booting Secret #1: Everything boots!
In fact, all of the above messages came directly or indirectly from the boot sector of the device.
That's the way the PC works, based on the BIOS setup (that's up to you) the BIOS will load the first sector of the
Initial Program Load device to 7C00h, perform a few checks and then jump to 7C00h. Everything boots.
(Of course there are old computers with USB that can't boot a flash drive, but we're not concerned about those here).

USB Booting Secret #2: What happens in the boot sector, stays in the boot sector!
When it comes to USB booting there are basically 4 types of computers:
    PC without USB, or with USB and can't boot USB because of old BIOS firmware.
    PC that always boots USB with floppy disk emulation.
    PC that always boots USB with hard drive emulation.
    PC that examines the boot sector to determine the type of emulation and/or with BIOS selection setup.
Because #1 - everything boots and #2 - booting occurs no matter what's in the boot sector (it does of course have to
pass a few simple BIOS checks), we can come up with a simple USB booting method designed specifically for
OS development.

The floppy disk is dead, long live the floppy disk!

Tip # 1
The FAT12 floppy disk format is simple, easy and universal.
Transfering files to the USB is easy and it will run from any PC that can boot from USB.
Use CHS for access and don't assume floppy disk geometry.

Tip # 2
Ask and you shall receive.
Later on, in the second stage, use int 13h function ah=8 to obtain and save the BIOS emulated geometry. This
information can used later to calculate CHS.
Code:
  push dx
  push es
  mov ah, 8
  int 13h                       ; get drive parameters
  mov [DRIVE_TYPE], bl
  and cx, 3Fh                   ; maximum sector number
  mov [SECTORS_PER_TRACK], cx
  mov [NUMBER_OF_DRIVES], dl
  movzx dx, dh                  ; maximum head number
  add dx, 1
  mov [NUMBER_OF_HEADS], dx
  pop es
  pop dx
  mov [DRIVE_NUMBER], dl    

Presented here is simple boot sector / boot loader.
The next 35 sectors are loaded to 0:600h. The loaded second stage (filled with "nop" to make it 17 1/2 K in size)
displays a message to the screen.
5 lines of data statements follow to create a basic FAT12 file system structure.


Code:
; Original code by Mike Gonta, Public Domain 2011

LOAD_ADDRESS                      equ 600h

use16
org 7C00h
  jmp start
  nop
  db '        '
  dw 512                        ; bytes per sector
  db 1                          ; sectors per cluster
  dw 36                         ; reserved sector count
  db 2                          ; number of FATs
  dw 16*14                      ; root directory entries
  dw 18*2*80                    ; sector count
  db 0F0h                       ; media byte
  dw 9                          ; sectors per fat
  dw 18                         ; sectors per track
  dw 2                          ; number of heads
  dd 0                          ; hidden sector count
  dd 0                          ; number of sectors huge
  db 0                          ; drive number
  db 0                          ; reserved
  db 29h                        ; signature
  dd 0                          ; volume ID
  db '           '              ; volume label
  db 'FAT12   '                 ; file system type
  
start:
  xor ax, ax
  mov ds, ax
  mov es, ax
  mov ss, ax
  mov sp, 7C00h
    
  mov bx, LOAD_ADDRESS
  mov cx, 2                     ; track 0, sector 2
  xor dh, dh                    ; side 0
  mov ax, 223h                  ; read 35 sectors
  test dl, dl
  jne .1
  mov ax, 211h                  ; read 17 sectors
  call read
  jc exit
  add bx, 512*17
  mov cx, 1                     ; track 0, sector 1
  mov dh, 1                     ; side 1
  mov ax, 212h                  ; read 18 sectors
.1:
  call read
  jc exit

  jmp 0:LOAD_ADDRESS
  
read:
  mov bp, 2                     ; 3 tries
.1:
  push ax
  int 13h
  jnc .2
  sub bp, 1
  jc .2
  xor ax, ax
  int 13h
  pop ax
  jmp .1
.2:
  pop bp
  ret
 
print:
  mov ah, 0Eh
  xor bh, bh
.1:
  mov al, [si]
  lea si, [si+1]
  test al, al
  je .2
  int 10h
  jmp .1
.2:
  ret
  
exit:
  mov si, boot_drive_read_error
  call print
  mov ah, 10h
  int 16h
  int 19h
   
boot_drive_read_error:
  db 'Boot drive read error!', 13, 10
  db 'Press any key to restart.', 13, 10, 0
  times 510-($-$$)                db 0
                                  dw 0AA55h

use16
org LOAD_ADDRESS
stage2:
  times 512*34 db 90h
  mov si, message
  call stage2_print
  mov ah, 10h
  int 16h
  int 19h
  
stage2_print:
  mov ah, 0Eh
  xor bh, bh
.1:
  mov al, [si]
  lea si, [si+1]
  test al, al
  je .2
  int 10h
  jmp .1
.2:
  ret
  
message:
  db 'USB booting is easy', 13, 10
  db 'Press any key to restart.', 13, 10, 0  
  times (512*35)-($-$$)           db 0
  
fat1:                           ; empty FAT12 file system
  db 0F0h, 0FFh, 0FFh
  times 512*9-($-fat1)            db 0
fat2:
  db 0F0h, 0FFh, 0FFh
  times 512*9-($-fat2)            db 0
root:
  times 512*14-($-root)           db 0    
Fixed bug reported by revolution.
Edited source code (removed extraneous code) to simplify presentation.
more USB Booting Secrets
How to transfer a bootable image to the USB flash drive

_________________
Mike Gonta
look and see - many look but few see

https://mikegonta.com


Last edited by Mike Gonta on 20 Aug 2011, 14:36; edited 5 times in total
Post 31 Dec 2010, 18:54
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20344
Location: In your JS exploiting you and your system
revolution 31 Dec 2010, 20:26
[DRIVE_NUMBER]=0 always. Looks like a bug to me.
Mike Gonta wrote:
Use CHS for access and don't assume floppy disk geometry.
Why do you always assume 18 sectors per track?
Post 31 Dec 2010, 20:26
View user's profile Send private message Visit poster's website Reply with quote
Mike Gonta



Joined: 26 Dec 2010
Posts: 243
Mike Gonta 31 Dec 2010, 20:51
revolution wrote:
[DRIVE_NUMBER]=0 always. Looks like a bug to me.
That's just a placeholder in the assembled code which is updated with the saved BIOS drive number in dl.
revolution wrote:
Why do you always assume 18 sectors per track?
Also just a place holder which is updated with the return parameters of int 13h, ah=8.
This same code boots and runs on any PC that can boot USB (it will also work on a floppy disk).

_________________
Mike Gonta
look and see - many look but few see

https://mikegonta.com
Post 31 Dec 2010, 20:51
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20344
Location: In your JS exploiting you and your system
revolution 31 Dec 2010, 21:26
The bug is here:
Code:
  push dx
  push es
...
  pop dx
  mov [DRIVE_NUMBER], dl ;dl=0
  pop es ;es=????    
Post 31 Dec 2010, 21:26
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20344
Location: In your JS exploiting you and your system
revolution 31 Dec 2010, 21:32
Mike Gonta wrote:
Also just a place holder which is updated with the return parameters of int 13h, ah=8.
Code:
  mov ax, 211h                  ; read 17 sectors
  call read
  jc exit
  add bx, 512*17
  mov cx, 1                     ; track 0, sector 1
  mov dh, 1                     ; side 1
  mov ax, 212h                  ; read 18 sectors    
Looks rather fixed at 18 sectors to me. Question
Post 31 Dec 2010, 21:32
View user's profile Send private message Visit poster's website Reply with quote
Mike Gonta



Joined: 26 Dec 2010
Posts: 243
Mike Gonta 31 Dec 2010, 22:25
revolution wrote:
The bug is here:
Code:
  push dx
  push es
...
  pop dx
  mov [DRIVE_NUMBER], dl ;dl=0
  pop es ;es=????    

Thank you.
Fixed it. I wasn't paying attention to the order of the pushes.

_________________
Mike Gonta
look and see - many look but few see

https://mikegonta.com
Post 31 Dec 2010, 22:25
View user's profile Send private message Visit poster's website Reply with quote
Mike Gonta



Joined: 26 Dec 2010
Posts: 243
Mike Gonta 31 Dec 2010, 22:34
revolution wrote:
Mike Gonta wrote:
Also just a place holder which is updated with the return parameters of int 13h, ah=8.
Code:
  mov ax, 211h                  ; read 17 sectors
  call read
  jc exit
  add bx, 512*17
  mov cx, 1                     ; track 0, sector 1
  mov dh, 1                     ; side 1
  mov ax, 212h                  ; read 18 sectors    
Looks rather fixed at 18 sectors to me. Question

This is the part that reads from the flash drive that boots with floppy drive emulation. The test for the drive number is
just before it.
Code:
  mov ax, 223h                  ; read 35 sectors
  test dl, dl
  jne .1    
If dl=80h (hard drive emulation) the code jumps past this code to here.
Code:
.1:
  call read
  jc exit    
And reads 35 sectors.
The code to convert LBA to CHS based on the obtained values for SECTORS_PER_TRACK and NUMBER_OF_HEADS is
trivial but not required for loading 35 sectors from LBA=1.

_________________
Mike Gonta
look and see - many look but few see

https://mikegonta.com
Post 31 Dec 2010, 22:34
View user's profile Send private message Visit poster's website Reply with quote
Mac2004



Joined: 15 Dec 2003
Posts: 314
Mac2004 02 Jan 2011, 12:18
I tested Mike's code on 2 different machines (amd64 3500+ and 4000+). Boot example seems to work nicely.

Should this thread be added to the FAQ section? These booting issues
are frequently asked questions.

regards
Mac2004
Post 02 Jan 2011, 12:18
View user's profile Send private message Reply with quote
Mike Gonta



Joined: 26 Dec 2010
Posts: 243
Mike Gonta 09 Jan 2011, 14:35
Mac2004 wrote:
I tested Mike's code on 2 different machines (amd64 3500+ and 4000+). Boot example seems to work nicely.
Hi Mac2004,
Thanks for testing.
The small step from antiquated floppy disk to USB flash drive seems to be a gigantic hurtle for the OS dev beginner.

_________________
Mike Gonta
look and see - many look but few see

https://mikegonta.com
Post 09 Jan 2011, 14:35
View user's profile Send private message Visit poster's website Reply with quote
Mac2004



Joined: 15 Dec 2003
Posts: 314
Mac2004 09 Jan 2011, 18:05
Mike Gonta wrote:
Mac2004 wrote:
I tested Mike's code on 2 different machines (amd64 3500+ and 4000+). Boot example seems to work nicely.
Hi Mac2004,
Thanks for testing.
The small step from antiquated floppy disk to USB flash drive seems to be a gigantic hurtle for the OS dev beginner.


Most of modern bioses support usb booting nicely. Smile

No problem Smile Thank you for releasing the code.

Regards
Mac2004
Post 09 Jan 2011, 18:05
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.