Booting
Booting¶
Steps:
1. POST (Power On Self Test)
2. BIOS Firmware
- Initialize CPU, Memory, etc.
- Check for hardware errors
- Search for boot loader
3. Boot loader
- In the MBR (Master Boot Record)/Boot Sector. The first 512 bytes of the device. The last bytes of this sector must end in 55AA.
- Transfer from 16 bit to real mode
Boot loader¶
References:
- Common functions
Custom Boot loader:
[BITS 16] ; Start in 16 bit mode
[ORG 0x7c00] ; Start Code at this address
CODE_OFFSET equ 0x8
DATA_OFFSET equ 0x10
start:
cli ; Clear Interrupts
mov ax, 0x00
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x7c00 ; Start the stack at 0x7c00 going up to 0x0000
sti ; Enable Interrupts
jmp load_PM
mov si, message ; Move message address into the SI register
print:
lodsb ; Deference address at SI and load into the AL register. Then increment the SI register
cmp al, 0 ; Check if reached the end of the string
je done
mov ah, 0x0E ; Set the "display char" argument
int 0x10 ; Send the common/video Interrupt command
jmp print ; Continue the print loop
done:
cli ; Clear Interrupts
hlt ; Stop the CPU
load_PM:
cli ; Clear Interrupts
lgdt[gdt_descriptor] ; Load the GDT from the descriptor
mov eax, cr0 ; Clear the CR0 register
or al, 1 ; Set the Protected Mode enable
mov cr0, eax
jmp CODE_OFFSET:pmode_main
message:
db "Hello World", 0
; GDT Implementation https://wiki.osdev.org/Global_Descriptor_Table
gdt_start:
db 0x00000000 ; NULL entry
db 0x00000000 ; GDT Entry 1
; Code Segment Descriptor https://wiki.osdev.org/Global_Descriptor_Table#Segment_Descriptor
dw 0xFFFF ; Limit
dw 0x0000 ; Base
db 0x00 ; Base
db 10011010b ; Access Byte: Present Bit, Code Segment Bit, Executable Bit, Read Bit
db 11001111b ; Flags and Limit Byte: Granularity Flag, 4KB Blocks, 32bit segment
db 0x00 ; Base
; Data Segment Descriptor https://wiki.osdev.org/Global_Descriptor_Table#Segment_Descriptor
dw 0xFFFF ; Limit
dw 0x0000 ; Base
db 0x00 ; Base
db 10010010b ; Access Byte: Present Bit, Code Segment Bit, Read Bit
db 11001111b ; Flags and Limit Byte: Granularity Flag, 4KB Blocks, 32bit segment
db 0x00 ; Base
gdt_end:
gdt_descriptor:
dw gdt_end - gdt_start - 1; Size of GDT
dd gdt_start ; Start of GDT Address
[BITS 32]
pmode_main:
mov ax, DATA_OFFSET ; Setup 32 bit registers
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ebp, 0x9C00 ; Setup stack
mov esp, ebp
in al, 0x92 ;
or al, 2 ;
out 0x92, al ;
times 510 - ($ -$$) db 0 ; Pad the data so that we can have the full 512 block
db 0x55 ; Ending data
db 0xAA
Build & Run:
>>> nasm -f bin boot.asm -o boot.bin
>>> hexyl boot.bin
┌────────┬─────────────────────────┬─────────────────────────┬────────┬────────┐
│00000000│ fa b8 00 00 8e d8 8e c0 ┊ 8e d0 bc 00 7c fb be 1e │××⋄⋄××××┊×××⋄|×ו│
│00000010│ 7c ac 3c 00 74 06 b4 0e ┊ cd 10 eb f5 fa f4 48 65 │|×<⋄t•×•┊ו××××He│
│00000020│ 6c 6c 6f 20 57 6f 72 6c ┊ 64 00 00 00 00 00 00 00 │llo Worl┊d⋄⋄⋄⋄⋄⋄⋄│
│00000030│ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 00 00 │⋄⋄⋄⋄⋄⋄⋄⋄┊⋄⋄⋄⋄⋄⋄⋄⋄│
│* │ ┊ │ ┊ │
│000001f0│ 00 00 00 00 00 00 00 00 ┊ 00 00 00 00 00 00 55 aa │⋄⋄⋄⋄⋄⋄⋄⋄┊⋄⋄⋄⋄⋄⋄U×│
└────────┴─────────────────────────┴─────────────────────────┴────────┴────────┘
>>> qemu-system-x86_64 -hda ./boot.bin
Linux¶
Booting modern Intel CPUs
https://binarydebt.wordpress.com/2018/10/06/how-does-an-x86-processor-boot/
ArchLinux Boot process
Linux Insides Booting
- Real Mode
- Start executing commands from 8086 reset vector
3.
Linux Bootloaders:
- BIOS
- MBR
- GRUB
- Kernel
- INIT/Systemd
Mac Booting¶
Booting on the Apple T2
Mac Secure Boot
AsahiLinux Boot Process
- https://github.com/AsahiLinux/docs/wiki/SW%3ABoot
- https://support.apple.com/guide/security/boot-process-secac71d5623/web