Skip to content

Commit

Permalink
Entering Protected Mode
Browse files Browse the repository at this point in the history
  • Loading branch information
taikiy committed Feb 14, 2023
1 parent fc44421 commit 82f6dae
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 48 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Documents in this repo assumes MacOS, but one should be able to follow the steps
# Sections

1. [Real Mode Development](./doc/real_mode_development.md)
2. [Protected Mode Development](./doc/protected_mode_development.md)

# Resources

Expand Down
97 changes: 50 additions & 47 deletions boot.asm
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
ORG 0
ORG 0x7c00
BITS 16 ; 16-bit (real mode)

CODE_SEG equ gdt_code - gdt_start
DATA_SEG equ gdt_data - gdt_start

; BIOS Parameter Block
; https://wiki.osdev.org/FAT#BPB_.28BIOS_Parameter_Block.29
_start:
Expand All @@ -9,67 +12,67 @@ _start:
times 33 db 0

init:
jmp 0x7c0:start
jmp 0:start

start:
; setup the data segment
cli ; Disable interrupts. We don't want interrupts messing with registers
mov ax, 0x7c0
mov ax, 0x00
mov ds, ax
mov es, ax
mov ax, 0x00
mov ss, ax
mov sp, 0x7c00
sti ; Enables interrups

; Disk interrupt preparation
mov ah, 0x02 ; READ SECTOR command
mov al, 0x01 ; Read 1 sector
mov ch, 0x00 ; Cylinder number 0
mov cl, 0x02 ; Sector number 2
mov dh, 0x00 ; Head number 0
; We don't set DL. BIOS sets it to the booted disk
mov bx, buffer ; Data read will be buffered at ES:BX
int 0x13

jc error ; if the carry flag is set (error), jump

mov si, buffer
call print

.load_protected:
cli
lgdt[gdt_descriptor]
mov eax, cr0
or al, 1
mov cr0, eax
jmp CODE_SEG:load32

; Global Descriptor Table
gdt_start:
gdt_null: ; 64 bits of zeros
dd 0
dd 0
; Offset 0x8
gdt_code: ;; CS should point to this
dw 0xffff ; Segment Limit 0-15 bits
dw 0 ; Base first 0-15 bits
db 0 ; Base 16-23 bits
db 0x9a ; Access Byte
db 11001111b ; High and Low 4-bit flags
db 0 ; Base 24-31 bits
; Offset 0x10
gdt_data: ;; DS, SS, ES, FS, GS
dw 0xffff ; Segment Limit 0-15 bits
dw 0 ; Base first 0-15 bits
db 0 ; Base 16-23 bits
db 0x92 ; Access Byte
db 11001111b ; High and Low 4-bit flags
db 0 ; Base 24-31 bits
gdt_end:
gdt_descriptor:
dw gdt_end - gdt_start - 1
dd gdt_start

[BITS 32]
load32:
mov ax, DATA_SEG
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov ebp, 0x00200000
mov esp, ebp
cld ; Clears direction flag
cli ; Disables interrupts
hlt ; This hangs the computer


error:
mov si, error_message
call print

print:
; setup INT10h params
mov ah, 0eh ; Teletype output
mov bx, 0 ; bh = page number, bl = color

.loop:
lodsb ; Load a byte from DS:SI into AL, then increase SI (see "Notes" in ./doc/real_mode_development.md)

cmp al, 0 ; if AL contains a null-byte, stop
je .done

int 0x10 ; BIOS interrupt call 0x10. https://en.wikipedia.org/wiki/INT_10H

jmp .loop

.done:
ret

error_message:
db 'Failed to load sector', 0

times 510 - ($ - $$) db 0 ; Pad the boot sector to 510 bytes
dw 0xAA55 ; Boot signature. 55AA (2 bytes) in the little-endian

;; Everything under here is at the second sector from 0x7c00 (0x7e00)

buffer:
72 changes: 72 additions & 0 deletions doc/protected_mode_development.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Protected Mode Development

Protected mode is an operation mode of x86 architectures. It gives access to 4GB of address space, memory protection, and much more. ([osdev wiki](https://wiki.osdev.org/Protected_mode))

## Memory and Hardware Protection

There are different protection levels in the processor. Levels are called _Rings_. The kernel runs in _Ring 0_. This is the most privileged mode that can talk with hardware and write data to any memory address. _Ring 1_ and _2_ are generally not used, but can be used for device drivers. _Ring 3_ is the least privileged level which is used to run user code. This prevents user applications from overwriting kernel memory, talking with hardware directly, accessing other processes' memory, and using privileged instructions (i.e., `sti`, `cli`).

## Memory access

### Selector Memory Scheme

What we know as _segmentation_ registers in Real Mode become _selector_ registers in Protected Mode. _Selectors_ point to data structures that describe memory ranges and the permissions (ring level) require to access a given range.

### Paging Memory Scheme

Paging memory scheme maps virtual memory addresses to physical memory addresses somewhere entirely different in memory. This allows user processes to believe that they are loaded into the same memory address, and makes it impossible for a user program to see the address space of other running programs. As far as a program is concerned, it is the only process running. Note that all virtual and physical addresses need to be divisible by 4096.

### 32-bit instructions

In Protected Mode, we gain access to 32-bit instructions, which enable easy access to 32-bit registers, thus 4GB memory.

# Development

## 1. Entering Protected Mode

We create entries for Global Descriptor Table (GDT) and load its address into GDT register by `lgdt` instruction, with additional parameters to enter Protected Mode ([osdev wiki](https://wiki.osdev.org/GDT)). We will use the GDT default values since we'll be using the paging memory scheme.

## 2. Verify using LLDB

Since this repo assumes you are using MacOS, we need to use LLDB instead of GDB. Here's how:

```
# Launch QEMU with gdb server enabled
# '-s' shorthand for -gdb tcp::1234
# '-S' freeze CPU at startup (use 'c' to start execution)
> qemu-x86-64 -hda ./boot.bin -s -S &
> lldb
(lldb) gdb-remote 1234 # connects to gdb server on localhost:1234
Process 1 stopped
* thread #1, stop reason = signal SIGTRAP
frame #0: 0x000000000000fff0
-> 0xfff0: addb %al, (%rax)
0xfff2: addb %al, (%rax)
0xfff4: addb %al, (%rax)
0xfff6: addb %al, (%rax)
Target 0: (No executable module.) stopped.
(lldb) c # continue
Process 1 resuming
(lldb) process interrupt # now the bootloader should come to a halt
Process 1 stopped
* thread #1, stop reason = signal SIGINT
frame #0: 0x0000000000007c68
-> 0x7c68: jmp 0x7c68
0x7c6a: addb %al, (%rax)
0x7c6c: addb %al, (%rax)
0x7c6e: addb %al, (%rax)
Target 0: (No executable module.) stopped.
(lldb) register read
general:
rax = 0x0000000000000011
...
rbp = 0x0000000000200000
rsp = 0x0000000000200000
...
cs = 0x00000008 # Code Segment = 8 means Protected Mode (?)
ss = 0x00000010
ds = 0x00000010
es = 0x00000010
fs = 0x00000010
gs = 0x00000010
```
8 changes: 7 additions & 1 deletion doc/real_mode_development.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@

Bootloader is a set of CPU instructions (usually written in assembly) that is loaded by the BIOS when a PC is booted. Bootloader's code sits at 0x7c00 when loaded into the memory, and must be 1-sector (= 512 bytes) long. The end of the bootloader code is marked by 2-byte signature `0x55AA`.

BIOS operates in _Real Mode_. Real Mode (aka. read address mode) is an operating mode available to all x86-compatible CPUs. All code in real mode is required to be 16 bits. Addresses in real mode correspond to real locations in memory. It uses a 20-bit _segmented memory_ address space (= 1MB of addressable memory) and unlimited direct software access to all addressable memory, I/O addresses and peripheral hardware. It does not provide memory protection, multitasking, or code privilege levels. [(wiki)](https://en.wikipedia.org/wiki/Real_mode)
## Real Mode

BIOS operates in _Real Mode_. Real Mode (aka. read address mode) is an operating mode available to all x86-compatible CPUs. All code in real mode is required to be 16 bits. Addresses in real mode correspond to real locations in memory.

Real Mode uses a 20-bit _segmented memory_ address space (= 1MB of addressable memory) and unlimited direct software access to all addressable memory, I/O addresses and peripheral hardware. It does not provide memory protection, multitasking, or code privilege levels. [(wiki)](https://en.wikipedia.org/wiki/Real_mode)

# Development

## 1. Printing a string to the screen

Expand Down

0 comments on commit 82f6dae

Please sign in to comment.