Grub stuff

This commit is contained in:
Adrien Bourmault 2019-02-10 16:18:32 +01:00
parent 01e0c9fe01
commit 8114333370
3 changed files with 8 additions and 375 deletions

View File

@ -27,12 +27,13 @@ This folder contains the source for OS/K's bootloader.
OS/K being intended to only run on x86-64 systems, we have not divided
this folder into one sub-folder per architecture.
It is divided in two parts each of exactly 512 bytes:
- mbr.s (and its auxiliary file mbr.inc)
This is our Master Boot Record (MBR). It switches to long mode
(64 bits mode) then loads the second half of the bootloader.
The MBR must be placed precisely on the first sector of the hard drive.
The bootloader itself is external to the OS/K project. We are using GRUB 2 to load
our kernel loader in memory.
- loader.s
This is the Kernel Loader. It switches to long mode and makes stuff.
The kernel loader, that we call the loader, is the main subject of this folder.
This loader is intended to load the ELF64 kernel at the specified address and
prepare it for the hard work it have to do :
- Parsing the ELF64
- Load the kernel
- Prepare a structure for it with memory map, cpu infos, and other devices infos.

View File

@ -1,191 +0,0 @@
;=----------------------------------------------------------------------------=;
; GNU GPL OS/K ;
; ;
; Desc: Bootsector for OS/K ;
; (x86_64 architecture only) ;
; ;
; ;
; Copyright © 2018-2019 The OS/K Team ;
; ;
; This file is part of OS/K. ;
; ;
; OS/K 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 ;
; any later version. ;
; ;
; OS/K 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 OS/K. If not, see <https://www.gnu.org/licenses/>. ;
;=----------------------------------------------------------------------------=;
;; BOOT "SEGMENT"
%define BOOT_SEG 0x07c0 ; (BOOT_SEG << 4) + BOOT_OFF = 0x007c00
%define BOOT_OFF 0x0000
;; STACK "SEGMENT"
%define STACK_SEG 0x0600 ; (STACK_SEG << 4) + STACK_OFF = 0x007000
%define STACK_OFF 0x1000
;; DISK BUFFER "SEGMENT"
%define BUFFER_SEG 0x2000 ; (BUFFER_SEG << 4) + BUFFER_OFF = 0x020000
%define BUFFER_OFF 0x0000
;; SECOND STAGE LOADER "SEGMENT"
%define LOAD_SEG 0x0000 ; (LOAD_SEG << 4) + LOAD_OFF = 0x001000
%define LOAD_OFF 0x1000
[BITS 16] ; Ensure 16-bit code (because fuck UEFI)
Intro:
jmp short _start ; Jump over the BIOS PARAMETER BLOCK
nop ; Required by BIOS to recognize the Disk loul
BPB:
;---------------------------------------------------;
; Disk description table ;
;---------------------------------------------------;
%define OEMName bp+0x03 ; Disk label
%define bytesPerSector bp+0x0b ; Bytes per sector
%define sectorsPerCluster bp+0x0d ; Sectors per cluster
%define reservedSectors bp+0x0e ; Reserved sectors
%define fats bp+0x10 ; Number of fats
%define rootDirEntries bp+0x11 ; Number of entries in root dir
%define sectors bp+0x13 ; Logical sectors
%define mediaType bp+0x15 ; Media descriptor byte
%define fatSectors bp+0x16 ; Sectors per FAT
%define sectorsPerTrack bp+0x18 ; Sectors per track
%define heads bp+0x1a ; Number of sides/heads
%define hiddenSectors bp+0x1c ; Hidden sectors
%define hugeSectors bp+0x20 ; LBA sectors
%define biosBootdrvNum bp+0x24 ; Bootdrv number
%define reserved bp+0x25 ; This is not used
%define bootSignature bp+0x26 ; Bootdrv signature
%define volumeId bp+0x27 ; Volume ID
%define volumeLabel bp+0x2b ; Volume Label
%define fatTypeLabel bp+0x36 ; File system type
times 0x3b db 0x00 ; ALLOCATE THE SECTORS FOR THE BPB
;; ENTRY POINT
_start:
jmp BOOT_SEG:$+5 ; Fix the cs:ip registers with a vaudou magical trip
bootstrap:
jmp go
;; LOVELY DATA
FileNotFound db "First Stage ERROR : NO LOADER", 0
DiskError db "First Stage ERROR : DISK", 0
UserData dw 0
Bootdrv db 0
filename db "LOADER BIN"
;; GO !
go:
mov ax, BOOT_SEG ; Set segments to the location of the bootloader
mov ds, ax
mov es, ax
;; INIT STACK
cli
mov ax, STACK_SEG ; Init the stack
mov ss, ax ; Continue init the stack
mov sp, STACK_OFF ; Ok man, the stack is in 4K :O
sti
mov bp, (0x7c0-STACK_SEG) << 4 ; Correct bp (the disk description table)
;; INITIALIZE BOOT DISK
or dl, dl ; Verifying dl points actually to the boot drive
jz load_root
mov byte [Bootdrv], dl ; Another soul (the disk) saved!
mov ah, 0x08
int 0x13 ; int 0x13 : read drive parameters/geom
jc load_root
and cx, 0x003f ; Maximum sector number is the high bits 6-7 of cl
mov word [sectorsPerTrack], cx ; And whose low 8 bits are in ch
mov dl, dh ; Convert the maximum head number to a word with another vaudou magical trip
xor dh, dh
inc dx ; because head numbers start at zero
mov word [heads], dx ; Another soul (the heads number) saved!
;; LOAD THE ROOT DIRECTORY FROM DISK
load_root:
xor cx, cx
mov ax, 32 ; Size of root dir = (rootDirEntries * 32) / bytesPerSector
mul word [rootDirEntries] ; multiply by the total size of the root directory
div word [bytesPerSector] ; divide by the number of bytes used per sector
xchg cx, ax
mov al, byte [fats] ; Location of root dir = (fats * fatSectors) + reservedSectors
mul word [fatSectors] ; multiply by the sectors used
add ax, word [reservedSectors] ; increase ax by the reserved sectors
mov word [UserData], ax ; Start of user data = startOfRoot + numberOfRoot
add word [UserData], cx ; Add the size and location of the root directory
mov di, BUFFER_SEG ; Set the extra segment to the disk buffer
mov es, di
mov di, BUFFER_OFF ; Set es:di and load the root directory into the disk buffer
call read_sectors ; Read the sectors
;; FIND THE SECOND STAGE LOADER
mov di, BUFFER_OFF ; Set es:di to the disk buffer
mov cx, word [rootDirEntries] ; Search through all of the root dir entries
xor ax, ax ; Clear ax for the file entry offset
search_root:
xchg cx, dx ; Save cx because it's a loop counter
mov si, filename ; Load the filename
mov cx, 11 ; Compare first 11 bytes
rep cmpsb ; Compare si and di cx times
je load_fat ; We found the loader
add ax, 32 ; File entry offset
mov di, BUFFER_OFF ; Point back to the start of the entry
add di, ax ; Add the offset to point to the next entry
xchg dx, cx
loop search_root ; Continue to search for the file
;; ERROR...
mov si, FileNotFound ; Could not find the file
call print
call reboot
;; LOAD THE FAT FROM THE FILE
load_fat:
mov ax, word [es:di + 15] ; Get the file cluster at offset 26
push ax ; Store the FAT cluster
xor ax, ax ; Size of fat = (fats * fatSectors)
mov al, byte [fats] ; Move number of fats into al
mul word [fatSectors] ; Move fat sectors into bx
mov cx, ax ; Store in cx
mov ax, word [reservedSectors] ; Convert the first fat on the disk
mov di, BUFFER_OFF ; Set es:di and load the fat sectors into the disk buffer
call read_sectors ; Read the sectors
;; LOAD THE CLUSTERS OF THE LOADER AND JUMP
mov di, LOAD_SEG
mov es, di ; Set es:bx to where the file will load
mov di, LOAD_OFF
pop ax ; File cluster restored
call read_clusters ; Read clusters from the file
mov dl, byte [Bootdrv] ; Pass the boot Bootdrv into dl
jmp LOAD_SEG:LOAD_OFF ; Jump to the file loaded!
hlt ; This should never be hit...
; ...
; ...
; I hope....
; ...
call reboot
%include "boot/mbr/mbr.inc"
;; END
times 510 - ($ - $$) db 0 ; Pad remainder of boot sector with zeros
dw 0xaa55 ; Boot signature

View File

@ -1,177 +0,0 @@
;=----------------------------------------------------------------------------=;
; GNU GPL OS/K ;
; ;
; Desc: Bootsector for OS/K INCLUDED FUNCTIONS ;
; (x86_64 architecture only) ;
; ;
; ;
; Copyright © 2018-2019 The OS/K Team ;
; ;
; This file is part of OS/K. ;
; ;
; OS/K 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 ;
; any later version. ;
; ;
; OS/K 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 OS/K. If not, see <https://www.gnu.org/licenses/>. ;
;=----------------------------------------------------------------------------=;
[BITS 16]
read_clusters:
;---------------------------------------------------;
; Read file clusters, starting at the given cluster,;
; expects FAT to be loaded into the disk buffer. ;
; Please note that this may allocate up to 128KB ;
; of ram. ;
; ;
; Expects: AX = Starting cluster ;
; ES:DI = Location to load clusters ;
; ;
; Returns: None ;
; ;
;---------------------------------------------------;
pusha
push es
.cluster_loop:
xor bh, bh
xor dx, dx
push ax ; Get the cluster start = (cluster - 2) * sectorsPerCluster + UserData
sub ax, 2 ; Subtract 2
mov bl, byte [sectorsPerCluster] ; Sectors per cluster is a byte value
mul bx ; multiply (cluster - 2) * sectorsPerCluster
add ax, word [UserData] ; add the UserData
xor ch, ch
mov cl, byte [sectorsPerCluster] ; Sectors to read
call read_sectors ; Read the sectors
pop ax ; Current cluster number
xor dx, dx
;; Calculate next sector for FAT16 (cluster * 2)
mov bx, 2 ; Multiply the cluster by two (cluster is in ax)
mul bx
;; Load sector in RAM
push ds
push si
mov si, BUFFER_SEG
mov ds, si ; Temporarly set ds:si to the FAT buffer
mov si, BUFFER_OFF
add si, ax ; Point to the next cluster in the FAT entry
mov ax, word [ds:si] ; Load ax to the next cluster in FAT
pop si
pop ds
;; Next
cmp ax, 0xfff8 ; Check if we are at the end of the file?
jae .done
add di, 512 ; Add to the pointer offset
jnc .cluster_loop
;; Correct the buffer because an error will occur if the buffer in memory
mov dx, es ; overlaps a 64k page boundry, when di overflows
add dh, 0x10 ; it will trigger the carry flag, so correct
mov es, dx ; extra segment by 0x1000
jmp .cluster_loop ; Load the next file cluster
.done:
pop es
popa
ret
read_sectors:
;---------------------------------------------------;
; Read sectors starting at a given sector by ;
; the given times and load into a buffer. Please ;
; note that this may allocate up to 128KB of ram. ;
; ;
; Expects: AX = Starting sector ;
; CX = Number of sectors to read ;
; ES:DI = Location to load sectors ;
; ;
; Returns: None ;
; ;
;---------------------------------------------------;
pusha
push es
mov bx, di ; Convert es:di to es:bx for int 13h
.sector_loop:
push ax
push cx
xor dx, dx
div word [sectorsPerTrack] ; Divide the lba (value in ax) by sectorsPerTrack
mov cx, dx ; Save the absolute sector value
inc cx
xor dx, dx ; Divide by the number of heads
div word [heads] ; to get absolute head and track values
mov dh, dl ; Move the absolute head into dh
mov ch, al ; Low 8 bits of absolute track
shl ah, 1 ; High 2 bits of absolute track
shl ah, 1
shl ah, 1
shl ah, 1
shl ah, 1
shl ah, 1
or cl, ah ; Now cx is set with respective track and sector numbers
mov dl, byte [Bootdrv] ; Set correct Bootdrv for int 13h
mov di, 21 ; Try five times to read the sector because I love 21
.attempt_read:
mov ax, 0x0201 ; Read Sectors func of int 13h, read one sector
int 0x13 ; Call int 13h (BIOS disk I/O)
jnc .read_ok ; If no carry set, the sector has been read
xor ah, ah ; Reset Bootdrv func of int 13h
int 0x13 ; Call int 13h (BIOS disk I/O)
dec di ; Decrease read attempt counter
jnz .attempt_read ; Try to read the sector again
mov si, DiskError ; Error reading the disk :/
call print
jmp reboot
.read_ok:
pop cx
pop ax
inc ax ; Increase the next sector to read
add bx, word [bytesPerSector] ; Add to the buffer address for the next sector
jnc .next_sector
;; Fixing buffer because an error will occur if the buffer in memory
mov dx, es ; overlaps a 64k page boundry, when bx overflows
add dh, 0x10 ; it will trigger the carry flag, so correct
mov es, dx ; es segment by 0x1000
.next_sector:
loop .sector_loop
pop es
popa
ret
print:
;---------------------------------------------------;
; Print out a simple string. ;
; ;
; Expects: DS:SI = String to print ;
; ;
; Returns: None ;
; ;
;---------------------------------------------------;
lodsb ; Load byte from ds:si to al
or al, al ; If al is empty stop looping
jz .done ; Done looping and return
mov ah, 0x0e ; Teletype output
int 0x10 ; Video interupt
jmp print ; Loop untill string is null
.done:
ret
reboot:
xor ax, ax
int 0x16 ; Get a single keypress
mov ah, 0x0e ; Teletype output
mov al, 0x0d ; Carriage return
int 0x10 ; Video interupt
mov al, 0x0a ; Line feed
int 0x10 ; Video interupt
mov al, 0x0a ; Line feed
int 0x10 ; Video interupt
xor ax, ax
int 0x19 ; Reboot the system