Commit dce4e213 authored by Karsten Lehmann's avatar Karsten Lehmann
Browse files

feat: Moved file name to the end of the bootloader

parent 3a1ea6bc
......@@ -10,7 +10,7 @@ QEMU_FLOPPY_DRIVE_FLAGS = -drive if=floppy,index=0,format=raw
BOOTLOADER_BINARY = bootloader.bin
BOOTLOADER_SOURCE = bootloader.asm
FILENAME_OFFSET = 480
FILENAME_OFFSET = 498
TESTCODE_BINARY = TESTCODE.BIN
TESTCODE_SOURCE = tests/testcode.asm
......
;; Copyright (c) 2018 by Karsten Lehmann <mail@kalehmann.de>
;;
;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;; This bootloader loads a file with the name stored in the string file_name to
;; 07c0:0 and executes it. The boot sector will be passed in the dl register.
;; If there is an error while reading the file or there is no file with this
;; name, no error will be printed, since I was not able to also place a print
;; function in the 512 bytes of this bootloader.
;; MEMORY MAP
;; Description | Start address | Size
;; -------------------------------------------------------------------
;; This bootloader | 0x600 | 512 bytes
;; Stack | 0x1100 | 4096 bytes
;; Root directory table | 0x2200 | (estimated) 7168 bytes
;; First FAT | (estimated) 0x3d00 | (estimated) 4608 bytes
;; Loaded program | 0x7c00 |
;;; Copyright 2018 - 2020 by Karsten Lehmann <mail@kalehmann.de>
;;;
;;; This program is free software: you can redistribute it and/or modify
;;; it under the terms of the GNU General Public License as published by
;;; the Free Software Foundation, either version 3 of the License, or
;;; (at your option) any later version.
;;;
;;; This program is distributed in the hope that it will be useful,
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;;
;;; This bootloader loads a file with its 8.3 name stored at the offset 498 to
;;; the address 07c0:0 and executes it. The boot drive will be passed in the dl
;;; register.
;;; MEMORY MAP
;;; Description | Start address | Size
;;; -------------------------------------------------------------------
;;; This bootloader | 0x600 | 512 bytes
;;; Stack | 0x800 | 4096 bytes
;;; Root directory table | 0x2200 | (estimated) 7168 bytes
;;; First FAT | (estimated) 0x3d00 | (estimated) 4608 bytes
;;; Loaded program | 0x7c00 |
BITS 16
;;; Total size of the boot code in bytes
%define BootcodeSize 512
;;; Size of the default boot signature (0xAA55)
%define BootSignatureSize 2
;;; Size of an 8.3 filename in the directory table
%define FilenameSize 11
;;; Message displayed when the file is not found
%define FileNotFoundError 'Not found: '
;;; Size of the message displayed when a file is not found in bytes
%strlen FileNotFoundErrorSize FileNotFoundError
;;; Load the file to 0x7c0:0. This is also the location the BIOS loads a
;;; bootloader to.
%define FileSegment 0x7c0
;;; 0x7c0:0 is the current location of this bootloader.
%define InitialBootloaderSegment 0x7c0
;;; This number will be found at many bootloaders. It is a relict from the good
;;; old times™. Back then the people of the stone age stored their data on drives
;;; called floppy disks or diskettes. These devices had a spin able magnet
;;; storage medium. There are 5 attempts to make sure the motor reaches the
;;; correct speed.
%define MaxReadAttempts 5
%define RelocatedBootloaderSegment 0x60
%define DirectoryTableEntrySize 32
;;; Location of the root directory table right after the stack
%define RootDirPointer 0x2200
%define StackSegment 0x80
%define StackSize 4096
%macro cluster2LBA 0
;; This macro calculates the LBA from the cluster in ax and saves it in
......@@ -96,44 +122,33 @@ BITS 16
%%done:
%endmacro
;; Location of the root directory table right after the stack
%define ROOT_DIR_POINTER 0x2200
;; Load the file to 0x7c0:0. This is also the location the BIOS loads a
;; bootloader to.
%define FILE_SEGMENT 0x7c0
;; This number will be found at many bootloaders. It is a relict from the good
;; old times™. Back then the people of the stone age stored their data on drives
;; called floppy disks or diskettes. These devices had a spin able magnet
;; storage medium. There are 5 attempts to make sure the motor reaches the
;; correct speed.
%define MAX_READ_ATTEMPTS 5
;; This bootloader loads a file from a FAT12 formatted drive. According to the
;; FAT specification, the first three bytes should be used to jump to the
;; beginning of the code. Since jmp short start assembles into 2 bytes we add a
;; nop instruction.
;;; This bootloader loads a file from a FAT12 formatted drive. According to the
;;; FAT specification, the first three bytes should be used to jump to the
;;; beginning of the code. Since jmp short start assembles into 2 bytes we add a
;;; nop instruction.
jmp short start
nop
;; Bios Parameter Block, short BPB.
;;; Bios Parameter Block, short BPB.
OEMLabel: db "mkfs.fat"
SectorSize: dw 512
SectorsPerCluster: db 1
ReservedForBoot: dw 1
NumberOfFats: db 2
NumberOfRootDirEntries: dw 224
;; 1.440 MB floppy with a sector size of 512 bytes = 2880 sectors
;;; 1.440 MB floppy with a sector size of 512 bytes = 2880 sectors
LogicalSectors: dw 2880
;; The next byte describes the type of the used devices. More than one device
;; per type is possible.
;; 0xf0 3.5 inch, 2.88 MB, 2 heads, 36 sectors /
;; 3.5 inch, 1.44 MB, 2 heads, 18 sectors
;; 0xf9 3.5 inch, 720 KB, 2 heads, 9 sectors /
;; 5.25 inch, 1.2 MB, 2 heads, 15 sectors
;; 0xfd 5.25 inch, 360 KB, 2 heads, 9 sectors
;; 0xff 5.25 inch, 320 KB, 2 heads, 8 sectors
;; 0xfc 5.25 inch, 180 KB, 1 head, 9 sectors
;; 0xfe 5.25 inch, 160 KB, 1 head, 8 sectors
;; 0xf8 fixed disk
;;; The next byte describes the type of the used devices. More than one device
;;; per type is possible.
;;; 0xf0 3.5 inch, 2.88 MB, 2 heads, 36 sectors /
;;; 3.5 inch, 1.44 MB, 2 heads, 18 sectors
;;; 0xf9 3.5 inch, 720 KB, 2 heads, 9 sectors /
;;; 5.25 inch, 1.2 MB, 2 heads, 15 sectors
;;; 0xfd 5.25 inch, 360 KB, 2 heads, 9 sectors
;;; 0xff 5.25 inch, 320 KB, 2 heads, 8 sectors
;;; 0xfc 5.25 inch, 180 KB, 1 head, 9 sectors
;;; 0xfe 5.25 inch, 160 KB, 1 head, 8 sectors
;;; 0xf8 fixed disk
MediumByte: db 0xf0
SectorsPerFat: dw 9
SectorsPerTrack: dw 18
......@@ -141,12 +156,12 @@ NumberOfHeads: dw 2
HiddenSectors: dd 0
LargeSectors: dd 0
DriveNumber: dw 0
;; Boot signature, the version of the BPB
;;; Boot signature, the version of the BPB
Signature: db 41
VolumeID: dd 0
;; 11 bytes
;;; 11 bytes
VolumeLabel: db "sibolo "
;; 8 bytes
;;; 8 bytes
FileSystem: db "FAT12 "
start:
......@@ -158,26 +173,25 @@ start:
;; The new location will be 0x50:0
;; Clear the direction flag -> forward
cld
;; 0x7c0:0 is the current location of this bootloader.
;; Setup source segment and address
mov ax, 0x7c0
mov ax, InitialBootloaderSegment
mov ds, ax
xor si, si
;; Setup destination segment and address
mov ax, 0x60
mov ax, RelocatedBootloaderSegment
mov es, ax
xor di, di
;; Move 256 words
mov cx, 256
rep movsw
jmp 0x60:go_on
jmp RelocatedBootloaderSegment:go_on
go_on:
mov ds, ax
mov ax, 0x8c0
mov ax, StackSegment
mov ss, ax
;; Set 4K of stack
mov sp, 4096
mov sp, StackSize
;; Setup stack frame
mov bp, sp
;; Restore interrups
......@@ -197,21 +211,21 @@ go_on:
;; Get the size of the root directory table in sectors.
;; RootSize = (NumberOfRootDirEntries * EntrySize) / SectorSize
;; The size of an entry in the root directory table is 32 bytes
mov ax, 32
mov ax, DirectoryTableEntrySize
mul word [NumberOfRootDirEntries]
div word [SectorSize]
mov [RootSize], ax
;; Get FAT pointer
mul word [SectorSize]
add ax, ROOT_DIR_POINTER
add ax, RootDirPointer
mov word [FatPointer], ax
;; Load the root directory table
mov ax, [RootSize]
xor bx, bx
mov bl, [RootStartSector]
mov cx, ROOT_DIR_POINTER
mov cx, RootDirPointer
call readsectors
;; Load the first FAT into memory.
......@@ -233,7 +247,7 @@ readsectors:
mov [bp-2], ax
mov [bp-4], bx
mov [bp-6], cx
mov word [bp-8], MAX_READ_ATTEMPTS
mov word [bp-8], MaxReadAttempts
.read_loop:
;; Lets read data from the drive. There are at maximum 5 attempts to
......@@ -266,7 +280,7 @@ readsectors:
dec word [bp-8]
jnz .read_loop
;; Enter an endless loop if reading wasn't successful in the fifth try.
mov si, ReadError
mov si, ErrorIO
call print_error
.read_next_sector:
......@@ -276,7 +290,7 @@ readsectors:
inc word [bp-4]
mov ax, [SectorSize]
add [bp-6], ax
mov word [bp-8], MAX_READ_ATTEMPTS
mov word [bp-8], MaxReadAttempts
jmp .read_loop
.read_done:
......@@ -331,17 +345,17 @@ loop_over_root:
sub sp, 4
mov ax, [NumberOfRootDirEntries]
mov [bp-2], ax
mov word [bp-4], ROOT_DIR_POINTER
mov word [bp-4], RootDirPointer
.loop_over_root_loop:
mov ax, [bp-4]
call process_entry
add word [bp-4], 32
add word [bp-4], DirectoryTableEntrySize
dec word [bp-2]
jnz .loop_over_root_loop
;; At this point the file was not found, enter an endless loop
mov si, FNF
mov si, ErrorFileNotFound
call print_error
process_entry:
......@@ -362,15 +376,15 @@ process_entry:
;; of the root directory table entry + 26
;; [si+15] holds the first cluster.
mov ax, [si+15]
mov bx, FILE_SEGMENT
;; Load to FILE_SEGMENT:0
mov bx, FileSegment
;; Load to FileSegment:0
mov es, bx
xor bx, bx
call load_file
;; Pass the boot drive to the next stage.
mov dl, [BootDrive]
;; Far jump to the next stage
jmp FILE_SEGMENT:0
jmp FileSegment:0
print_error:
;; Prints the error string from the address in the si register.
......@@ -384,18 +398,34 @@ print_error:
jnz .loop
jmp $
;; DATA
;; The name of the file to load, this will be replaced later by the
;; installer of the bootloader.
FNF db "Not found: "
FileName db "PLACEHOLDER", 0
ReadError db "ReadError", 0
BootDrive db 0
RootStartSector db 0
RootSize db 0
FatPointer db 0
;; The bios loads exact 512 bytes. Fill this file with zeros to byte 510.
times 510-($-$$) db 0
;; The standard PC boot signature.
;;; DATA
BootDrive db 0
;; Short zero-terminated error message for IO problems
ErrorIO db "IO error", 0
FatPointer dw 0
RootSize dw 0
RootStartSector db 0
;; The BIOS loads exact 512 bytes.
;; Here come a few padding bytes to make sure this file is exactly 512
;; bytes in size.
times BootcodeSize \
- FileNotFoundErrorSize \
- FilenameSize \
- 1 \
- BootSignatureSize \
- ($ - $$) \
db 0
;; Short error message for the case that the file is not found.
;; The message itself has no zero terminator and therefore includes
;; the 8.3 filename of the file that should be booted.
ErrorFileNotFound db FileNotFoundError
;; Reserve eleven bytes for the name of the file to boot. The
;; placeholder will be replaced with the actual name by the program,
;; that installs the bootloader.
;; It is placed after the padding bytes to keep its offset in the
;; bootloader independent from changes it the code at 498.
FileName times FilenameSize db 0x32
;; Zero terminate the string with the file not found error
db 0
;; The last two bytes contain the standard PC boot signature.
dw 0xAA55
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment