mirror of
https://github.com/cfenollosa/os-tutorial.git
synced 2024-10-27 20:34:19 +00:00
Add Pandoc Support
- Add a Pandoc defaults file - Add a Pandoc template based on the default one - Add chapter headers to each section ### Usage To use, install Pandoc and ConTeXt, then simply run `pandoc -d ./pandoc.yaml` from the repo root. ### Maintenance When new chapters get added, the `pandoc.yaml` will need to be updated to include each new chapter's markdown file(s). ### Miscellaneous Notes - The PDF generated complies with PDF/A 1b:2005 by default. - The PDF also contains the source markdown files as attachments - All links are fully functional! - Includes a table of contents! With links to each section! ### Conclusion Enjoy!
This commit is contained in:
parent
7aff64740e
commit
7d932d43b3
1
.gitignore
vendored
1
.gitignore
vendored
@ -5,3 +5,4 @@
|
|||||||
*.elf
|
*.elf
|
||||||
*.sym
|
*.sym
|
||||||
.DS_STORE
|
.DS_STORE
|
||||||
|
os-tutorial.pdf
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
Environment
|
||||||
|
===========
|
||||||
|
|
||||||
*Concepts you may want to Google beforehand: linux, mac, terminal, compiler, emulator, nasm, qemu*
|
*Concepts you may want to Google beforehand: linux, mac, terminal, compiler, emulator, nasm, qemu*
|
||||||
|
|
||||||
**Goal: Install the software required to run this tutorial**
|
**Goal: Install the software required to run this tutorial**
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
Bootsector: Barebones
|
||||||
|
=====================
|
||||||
|
|
||||||
*Concepts you may want to Google beforehand: assembler, BIOS*
|
*Concepts you may want to Google beforehand: assembler, BIOS*
|
||||||
|
|
||||||
**Goal: Create a file which the BIOS interprets as a bootable disk**
|
**Goal: Create a file which the BIOS interprets as a bootable disk**
|
||||||
@ -25,7 +28,7 @@ e9 fd ff 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||||||
```
|
```
|
||||||
|
|
||||||
It is basically all zeros, ending with the 16-bit value
|
It is basically all zeros, ending with the 16-bit value
|
||||||
`0xAA55` (beware of endianness, x86 is little-endian).
|
`0xAA55` (beware of endianness, x86 is little-endian).
|
||||||
The first three bytes perform an infinite jump
|
The first three bytes perform an infinite jump
|
||||||
|
|
||||||
Simplest boot sector ever
|
Simplest boot sector ever
|
||||||
@ -38,12 +41,12 @@ simple assembler code:
|
|||||||
```nasm
|
```nasm
|
||||||
; Infinite loop (e9 fd ff)
|
; Infinite loop (e9 fd ff)
|
||||||
loop:
|
loop:
|
||||||
jmp loop
|
jmp loop
|
||||||
|
|
||||||
; Fill with 510 zeros minus the size of the previous code
|
; Fill with 510 zeros minus the size of the previous code
|
||||||
times 510-($-$$) db 0
|
times 510-($-$$) db 0
|
||||||
; Magic number
|
; Magic number
|
||||||
dw 0xaa55
|
dw 0xaa55
|
||||||
```
|
```
|
||||||
|
|
||||||
To compile:
|
To compile:
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
Bootsector: Print
|
||||||
|
=================
|
||||||
|
|
||||||
*Concepts you may want to Google beforehand: interrupts, CPU
|
*Concepts you may want to Google beforehand: interrupts, CPU
|
||||||
registers*
|
registers*
|
||||||
|
|
||||||
@ -14,7 +17,7 @@ is a general interrupt for video services.
|
|||||||
`0x0e` on `ah` tells the video interrupt that the actual function
|
`0x0e` on `ah` tells the video interrupt that the actual function
|
||||||
we want to run is to 'write the contents of `al` in tty mode'.
|
we want to run is to 'write the contents of `al` in tty mode'.
|
||||||
|
|
||||||
We will set tty mode only once though in the real world we
|
We will set tty mode only once though in the real world we
|
||||||
cannot be sure that the contents of `ah` are constant. Some other
|
cannot be sure that the contents of `ah` are constant. Some other
|
||||||
process may run on the CPU while we are sleeping, not clean
|
process may run on the CPU while we are sleeping, not clean
|
||||||
up properly and leave garbage data on `ah`.
|
up properly and leave garbage data on `ah`.
|
||||||
@ -39,7 +42,7 @@ jmp $ ; jump to current address = infinite loop
|
|||||||
|
|
||||||
; padding and magic number
|
; padding and magic number
|
||||||
times 510 - ($-$$) db 0
|
times 510 - ($-$$) db 0
|
||||||
dw 0xaa55
|
dw 0xaa55
|
||||||
```
|
```
|
||||||
|
|
||||||
You can examine the binary data with `xxd file.bin`
|
You can examine the binary data with `xxd file.bin`
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
Bootsector: Memory
|
||||||
|
==================
|
||||||
|
|
||||||
*Concepts you may want to Google beforehand: memory offsets, pointers*
|
*Concepts you may want to Google beforehand: memory offsets, pointers*
|
||||||
|
|
||||||
**Goal: Learn how the computer memory is organized**
|
**Goal: Learn how the computer memory is organized**
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
Bootsector: Stack
|
||||||
|
=================
|
||||||
|
|
||||||
*Concepts you may want to Google beforehand: stack*
|
*Concepts you may want to Google beforehand: stack*
|
||||||
|
|
||||||
**Goal: Learn how to use the stack**
|
**Goal: Learn how to use the stack**
|
||||||
@ -11,5 +14,5 @@ decremented)
|
|||||||
|
|
||||||
This lesson is quite straightforward, so jump ahead to the code.
|
This lesson is quite straightforward, so jump ahead to the code.
|
||||||
|
|
||||||
I suggest that you try accessing in-stack memory addresses by yourself,
|
I suggest that you try accessing in-stack memory addresses by yourself,
|
||||||
at different points in the code, and see what happens.
|
at different points in the code, and see what happens.
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
Bootsector: Functions and Strings
|
||||||
|
=================================
|
||||||
|
|
||||||
*Concepts you may want to Google beforehand: control structures,
|
*Concepts you may want to Google beforehand: control structures,
|
||||||
function calling, strings*
|
function calling, strings*
|
||||||
|
|
||||||
@ -52,7 +55,7 @@ endif:
|
|||||||
|
|
||||||
Think in your head in high level, then convert it to assembler in this fashion.
|
Think in your head in high level, then convert it to assembler in this fashion.
|
||||||
|
|
||||||
There are many `jmp` conditions: if equal, if less than, etc. They are pretty
|
There are many `jmp` conditions: if equal, if less than, etc. They are pretty
|
||||||
intuitive but you can always Google them
|
intuitive but you can always Google them
|
||||||
|
|
||||||
|
|
||||||
@ -119,7 +122,7 @@ to make sure that we are reading the correct data. File `boot_sect_print_hex.asm
|
|||||||
extends `boot_sect_print.asm` to print hex bytes, not just ASCII chars.
|
extends `boot_sect_print.asm` to print hex bytes, not just ASCII chars.
|
||||||
|
|
||||||
|
|
||||||
Code!
|
Code!
|
||||||
-----
|
-----
|
||||||
|
|
||||||
Let's jump to the code. File `boot_sect_print.asm` is the subroutine which will
|
Let's jump to the code. File `boot_sect_print.asm` is the subroutine which will
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
Bootsector: Segmentation
|
||||||
|
========================
|
||||||
|
|
||||||
*Concepts you may want to Google beforehand: segmentation*
|
*Concepts you may want to Google beforehand: segmentation*
|
||||||
|
|
||||||
**Goal: learn how to address memory with 16-bit real mode segmentation**
|
**Goal: learn how to address memory with 16-bit real mode segmentation**
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
*Concepts you may want to Google beforehand: hard disk, cylinder, head, sector,
|
Bootsector: Disk
|
||||||
|
================
|
||||||
|
|
||||||
|
*Concepts you may want to Google beforehand: hard disk, cylinder, head, sector,
|
||||||
carry bit*
|
carry bit*
|
||||||
|
|
||||||
**Goal: Let the bootsector load data from disk in order to boot the kernel**
|
**Goal: Let the bootsector load data from disk in order to boot the kernel**
|
||||||
@ -57,7 +60,7 @@ There are two quick options:
|
|||||||
|
|
||||||
1. Try the flag `-fda` for example, `qemu -fda boot_sect_main.bin` which will set `dl`
|
1. Try the flag `-fda` for example, `qemu -fda boot_sect_main.bin` which will set `dl`
|
||||||
as `0x00`, it seems to work fine then.
|
as `0x00`, it seems to work fine then.
|
||||||
2. Explicitly use the flag `-boot`, e.g. `qemu boot_sect_main.bin -boot c` which
|
1. Explicitly use the flag `-boot`, e.g. `qemu boot_sect_main.bin -boot c` which
|
||||||
automatically sets `dl` as `0x80` and lets the bootloader read data
|
automatically sets `dl` as `0x80` and lets the bootloader read data
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
*Concepts you may want to Google beforehand: 32-bit protected mode, VGA, video
|
32-bit: Print
|
||||||
|
=============
|
||||||
|
|
||||||
|
*Concepts you may want to Google beforehand: 32-bit protected mode, VGA, video
|
||||||
memory*
|
memory*
|
||||||
|
|
||||||
**Goal: Print on the screen when on 32-bit protected mode**
|
**Goal: Print on the screen when on 32-bit protected mode**
|
||||||
|
|
||||||
32-bit mode allows us to use 32 bit registers and memory addressing,
|
32-bit mode allows us to use 32 bit registers and memory addressing,
|
||||||
protected memory, virtual memory and other advantages, but we will lose
|
protected memory, virtual memory and other advantages, but we will lose
|
||||||
BIOS interrupts and we'll need to code the GDT (more on this later)
|
BIOS interrupts and we'll need to code the GDT (more on this later)
|
||||||
|
|
||||||
@ -18,7 +21,7 @@ The formula for accessing a specific character on the 80x25 grid is:
|
|||||||
|
|
||||||
`0xb8000 + 2 * (row * 80 + col)`
|
`0xb8000 + 2 * (row * 80 + col)`
|
||||||
|
|
||||||
That is, every character uses 2 bytes (one for the ASCII, another for
|
That is, every character uses 2 bytes (one for the ASCII, another for
|
||||||
color and such), and we see that the structure of the memory concatenates
|
color and such), and we see that the structure of the memory concatenates
|
||||||
rows.
|
rows.
|
||||||
|
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
32-bit: GDT
|
||||||
|
===========
|
||||||
|
|
||||||
*Concepts you may want to Google beforehand: GDT*
|
*Concepts you may want to Google beforehand: GDT*
|
||||||
|
|
||||||
**Goal: program the GDT**
|
**Goal: program the GDT**
|
||||||
@ -9,7 +12,7 @@ In 32-bit mode, segmentation works differently. Now, the offset becomes an
|
|||||||
index to a segment descriptor (SD) in the GDT. This descriptor defines
|
index to a segment descriptor (SD) in the GDT. This descriptor defines
|
||||||
the base address (32 bits), the size (20 bits) and some flags, like
|
the base address (32 bits), the size (20 bits) and some flags, like
|
||||||
readonly, permissions, etc. To add confusion, the data structures are split,
|
readonly, permissions, etc. To add confusion, the data structures are split,
|
||||||
so open the os-dev.pdf file and check out the figure on page 34 or the
|
so open the os-dev.pdf file and check out the figure on page 34 or the
|
||||||
Wikipedia page for the GDT.
|
Wikipedia page for the GDT.
|
||||||
|
|
||||||
The easiest way to program the GDT is to define two segments, one for code
|
The easiest way to program the GDT is to define two segments, one for code
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
32-bit: Enter
|
||||||
|
=============
|
||||||
|
|
||||||
*Concepts you may want to Google beforehand: interrupts, pipelining*
|
*Concepts you may want to Google beforehand: interrupts, pipelining*
|
||||||
|
|
||||||
**Goal: Enter 32-bit protected mode and test our code from previous lessons**
|
**Goal: Enter 32-bit protected mode and test our code from previous lessons**
|
||||||
@ -17,7 +20,7 @@ and take a look at the code.
|
|||||||
|
|
||||||
After entering 32-bit mode, we will call `BEGIN_PM` which is the entry point
|
After entering 32-bit mode, we will call `BEGIN_PM` which is the entry point
|
||||||
for our actual useful code (e.g. kernel code, etc). You can read the code
|
for our actual useful code (e.g. kernel code, etc). You can read the code
|
||||||
at `32bit-main.asm`. Compile and run this last file and you will see the two
|
at `32bit-main.asm`. Compile and run this last file and you will see the two
|
||||||
messages on the screen.
|
messages on the screen.
|
||||||
|
|
||||||
Congratulations! Our next step will be to write a simple kernel
|
Congratulations! Our next step will be to write a simple kernel
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
Kernel: Crosscompiler
|
||||||
|
=====================
|
||||||
|
|
||||||
*Concepts you may want to Google beforehand: cross-compiler*
|
*Concepts you may want to Google beforehand: cross-compiler*
|
||||||
|
|
||||||
**Goal: Create a development environment to build your kernel**
|
**Goal: Create a development environment to build your kernel**
|
||||||
@ -6,7 +9,7 @@ If you're using a Mac, you will need to do this process right away. Otherwise, i
|
|||||||
for a few more lessons. Anyway, you will need a cross-compiler once we jump to developing in a higher
|
for a few more lessons. Anyway, you will need a cross-compiler once we jump to developing in a higher
|
||||||
language, that is, C. [Read why](http://wiki.osdev.org/Why_do_I_need_a_Cross_Compiler%3F)
|
language, that is, C. [Read why](http://wiki.osdev.org/Why_do_I_need_a_Cross_Compiler%3F)
|
||||||
|
|
||||||
I'll be adapting the instructions [at the OSDev wiki](http://wiki.osdev.org/GCC_Cross-Compiler).
|
I'll be adapting the instructions [at the OSDev wiki](http://wiki.osdev.org/GCC_Cross-Compiler).
|
||||||
|
|
||||||
|
|
||||||
Required packages
|
Required packages
|
||||||
@ -63,10 +66,10 @@ tar xf gcc-4.9.1.tar.bz2
|
|||||||
mkdir gcc-build
|
mkdir gcc-build
|
||||||
cd gcc-build
|
cd gcc-build
|
||||||
../gcc-4.9.1/configure --target=$TARGET --prefix="$PREFIX" --disable-nls --disable-libssp --enable-languages=c --without-headers
|
../gcc-4.9.1/configure --target=$TARGET --prefix="$PREFIX" --disable-nls --disable-libssp --enable-languages=c --without-headers
|
||||||
make all-gcc
|
make all-gcc
|
||||||
make all-target-libgcc
|
make all-target-libgcc
|
||||||
make install-gcc
|
make install-gcc
|
||||||
make install-target-libgcc
|
make install-target-libgcc
|
||||||
```
|
```
|
||||||
|
|
||||||
That's it! You should have all the GNU binutils and the compiler at `/usr/local/i386elfgcc/bin`, prefixed by `i386-elf-` to avoid
|
That's it! You should have all the GNU binutils and the compiler at `/usr/local/i386elfgcc/bin`, prefixed by `i386-elf-` to avoid
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
Kernel: C
|
||||||
|
=========
|
||||||
|
|
||||||
*Concepts you may want to Google beforehand: C, object code, linker, disassemble*
|
*Concepts you may want to Google beforehand: C, object code, linker, disassemble*
|
||||||
|
|
||||||
**Goal: Learn to write the same low-level code as we did with assembler, but in C**
|
**Goal: Learn to write the same low-level code as we did with assembler, but in C**
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
Kernel: Barebones
|
||||||
|
=================
|
||||||
|
|
||||||
*Concepts you may want to Google beforehand: kernel, ELF format, makefile*
|
*Concepts you may want to Google beforehand: kernel, ELF format, makefile*
|
||||||
|
|
||||||
**Goal: Create a simple kernel and a bootsector capable of booting it**
|
**Goal: Create a simple kernel and a bootsector capable of booting it**
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
Checkpoint
|
||||||
|
==========
|
||||||
|
|
||||||
*Concepts you may want to Google beforehand: monolithic kernel, microkernel, debugger, gdb*
|
*Concepts you may want to Google beforehand: monolithic kernel, microkernel, debugger, gdb*
|
||||||
|
|
||||||
**Goal: Pause and organize our code a little bit. Then learn how to debug the kernel with gdb**
|
**Goal: Pause and organize our code a little bit. Then learn how to debug the kernel with gdb**
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
Video: Ports
|
||||||
|
============
|
||||||
|
|
||||||
*Concepts you may want to Google beforehand: I/O ports*
|
*Concepts you may want to Google beforehand: I/O ports*
|
||||||
|
|
||||||
**Goal: Learn how to use the VGA card data ports**
|
**Goal: Learn how to use the VGA card data ports**
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
Video: Driver
|
||||||
|
=============
|
||||||
|
|
||||||
*Concepts you may want to Google beforehand: VGA character cells, screen offset*
|
*Concepts you may want to Google beforehand: VGA character cells, screen offset*
|
||||||
|
|
||||||
**Goal: Write strings on the screen**
|
**Goal: Write strings on the screen**
|
||||||
@ -44,7 +47,7 @@ Like `kprint_at`, `print_char` allows cols/rows to be `-1`. In that case it retr
|
|||||||
the cursor position from the hardware, using the `ports.c` routines.
|
the cursor position from the hardware, using the `ports.c` routines.
|
||||||
|
|
||||||
`print_char` also handles newlines. In that case, we will position the cursor offset
|
`print_char` also handles newlines. In that case, we will position the cursor offset
|
||||||
to column 0 of the next row.
|
to column 0 of the next row.
|
||||||
|
|
||||||
Remember that the VGA cells take two bytes, one for the character itself and another one
|
Remember that the VGA cells take two bytes, one for the character itself and another one
|
||||||
for the attribute.
|
for the attribute.
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
Video: Scroll
|
||||||
|
=============
|
||||||
|
|
||||||
*Concepts you may want to Google beforehand: scroll*
|
*Concepts you may want to Google beforehand: scroll*
|
||||||
|
|
||||||
**Goal: Scroll the screen when the text reaches the bottom**
|
**Goal: Scroll the screen when the text reaches the bottom**
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
Interrupts
|
||||||
|
==========
|
||||||
|
|
||||||
*Concepts you may want to Google beforehand: C types and structs, include guards, type attributes: packed, extern, volatile, exceptions*
|
*Concepts you may want to Google beforehand: C types and structs, include guards, type attributes: packed, extern, volatile, exceptions*
|
||||||
|
|
||||||
**Goal: Set up the Interrupt Descriptor Table to handle CPU interrupts**
|
**Goal: Set up the Interrupt Descriptor Table to handle CPU interrupts**
|
||||||
@ -24,7 +27,7 @@ From now on, our C header files will also have include guards.
|
|||||||
Interrupts
|
Interrupts
|
||||||
----------
|
----------
|
||||||
|
|
||||||
Interrupts are one of the main things that a kernel needs to
|
Interrupts are one of the main things that a kernel needs to
|
||||||
handle. We will implement it now, as soon as possible, to be able
|
handle. We will implement it now, as soon as possible, to be able
|
||||||
to receive keyboard input in future lessons.
|
to receive keyboard input in future lessons.
|
||||||
|
|
||||||
@ -37,13 +40,13 @@ programming the IDT in assembly, we'll do it in C.
|
|||||||
|
|
||||||
`cpu/idt.h` defines how an idt entry is stored `idt_gate` (there need to be
|
`cpu/idt.h` defines how an idt entry is stored `idt_gate` (there need to be
|
||||||
256 of them, even if null, or the CPU may panic) and the actual
|
256 of them, even if null, or the CPU may panic) and the actual
|
||||||
idt structure that the BIOS will load, `idt_register` which is
|
idt structure that the BIOS will load, `idt_register` which is
|
||||||
just a memory address and a size, similar to the GDT register.
|
just a memory address and a size, similar to the GDT register.
|
||||||
|
|
||||||
Finally, we define a couple variables to access those data structures
|
Finally, we define a couple variables to access those data structures
|
||||||
from assembler code.
|
from assembler code.
|
||||||
|
|
||||||
`cpu/idt.c` just fills in every struct with a handler.
|
`cpu/idt.c` just fills in every struct with a handler.
|
||||||
As you can see, it is a matter
|
As you can see, it is a matter
|
||||||
of setting the struct values and calling the `lidt` assembler command.
|
of setting the struct values and calling the `lidt` assembler command.
|
||||||
|
|
||||||
@ -51,8 +54,8 @@ of setting the struct values and calling the `lidt` assembler command.
|
|||||||
ISRs
|
ISRs
|
||||||
----
|
----
|
||||||
|
|
||||||
The Interrupt Service Routines run every time the CPU detects an
|
The Interrupt Service Routines run every time the CPU detects an
|
||||||
interrupt, which is usually fatal.
|
interrupt, which is usually fatal.
|
||||||
|
|
||||||
We will write just enough code to handle them, print an error message,
|
We will write just enough code to handle them, print an error message,
|
||||||
and halt the CPU.
|
and halt the CPU.
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
|
Interrupts: IRQs
|
||||||
|
================
|
||||||
|
|
||||||
*Concepts you may want to Google beforehand: IRQs, PIC, polling*
|
*Concepts you may want to Google beforehand: IRQs, PIC, polling*
|
||||||
|
|
||||||
**Goal: Finish the interrupts implementation and CPU timer**
|
**Goal: Finish the interrupts implementation and CPU timer**
|
||||||
|
|
||||||
When the CPU boots, the PIC maps IRQs 0-7 to INT 0x8-0xF
|
When the CPU boots, the PIC maps IRQs 0-7 to INT 0x8-0xF
|
||||||
and IRQs 8-15 to INT 0x70-0x77. This conflicts with the ISRs
|
and IRQs 8-15 to INT 0x70-0x77. This conflicts with the ISRs
|
||||||
we programmed last lesson. Since we programmed ISRs 0-31,
|
we programmed last lesson. Since we programmed ISRs 0-31,
|
||||||
it is standard to remap the IRQs to ISRs 32-47.
|
it is standard to remap the IRQs to ISRs 32-47.
|
||||||
|
|
||||||
The PICs are communicated with via I/O ports (see lesson 15).
|
The PICs are communicated with via I/O ports (see lesson 15).
|
||||||
@ -12,13 +15,13 @@ The Master PIC has command 0x20 and data 0x21, while the slave has
|
|||||||
command 0xA0 and data 0xA1.
|
command 0xA0 and data 0xA1.
|
||||||
|
|
||||||
The code for remapping the PICs is weird and includes
|
The code for remapping the PICs is weird and includes
|
||||||
some masks, so check
|
some masks, so check
|
||||||
[this article](http://www.osdev.org/wiki/PIC) if you're curious.
|
[this article](http://www.osdev.org/wiki/PIC) if you're curious.
|
||||||
Otherwise, just look at `cpu/isr.c`, new code after we set the IDT
|
Otherwise, just look at `cpu/isr.c`, new code after we set the IDT
|
||||||
gates for the ISRs. After that, we add the IDT gates for IRQs.
|
gates for the ISRs. After that, we add the IDT gates for IRQs.
|
||||||
|
|
||||||
Now we jump to assembler, at `interrupt.asm`. The first task is to
|
Now we jump to assembler, at `interrupt.asm`. The first task is to
|
||||||
add global definitions for the IRQ symbols we just used in the C code.
|
add global definitions for the IRQ symbols we just used in the C code.
|
||||||
Look at the end of the `global` statements.
|
Look at the end of the `global` statements.
|
||||||
|
|
||||||
Then, add the IRQ handlers. Same `interrupt.asm`, at the bottom. Notice
|
Then, add the IRQ handlers. Same `interrupt.asm`, at the bottom. Notice
|
||||||
@ -31,7 +34,7 @@ a new `[extern irq_handler]`
|
|||||||
Now back to C code, to write the `irq_handler()` in `isr.c`. It sends some
|
Now back to C code, to write the `irq_handler()` in `isr.c`. It sends some
|
||||||
EOIs to the PICs and calls the appropriate handler, which is stored in an array
|
EOIs to the PICs and calls the appropriate handler, which is stored in an array
|
||||||
named `interrupt_handlers` and defined at the top of the file. The new structs
|
named `interrupt_handlers` and defined at the top of the file. The new structs
|
||||||
are defined in `isr.h`. We will also use a simple function to register
|
are defined in `isr.h`. We will also use a simple function to register
|
||||||
the interrupt handlers.
|
the interrupt handlers.
|
||||||
|
|
||||||
That was a lot of work, but now we can define our first IRQ handler!
|
That was a lot of work, but now we can define our first IRQ handler!
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
Interrupts: Timer
|
||||||
|
=================
|
||||||
|
|
||||||
*Concepts you may want to Google beforehand: CPU timer, keyboard interrupts, scancode*
|
*Concepts you may want to Google beforehand: CPU timer, keyboard interrupts, scancode*
|
||||||
|
|
||||||
**Goal: Implement our first IRQ handlers: the CPU timer and the keyboard**
|
**Goal: Implement our first IRQ handlers: the CPU timer and the keyboard**
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
|
Shell
|
||||||
|
=====
|
||||||
|
|
||||||
**Goal: Clean the code a bit and parse user input**
|
**Goal: Clean the code a bit and parse user input**
|
||||||
|
|
||||||
In this lesson we will do two things. First, we will clean up the code a bit, so it is ready
|
In this lesson we will do two things. First, we will clean up the code a bit, so it is ready
|
||||||
for further lessons. During the previous ones I tried to put things in the most predictable places,
|
for further lessons. During the previous ones I tried to put things in the most predictable places,
|
||||||
but it is also a good exercise to know when the code base is growing and adapt it to current
|
but it is also a good exercise to know when the code base is growing and adapt it to current
|
||||||
and further needs.
|
and further needs.
|
||||||
@ -52,7 +54,7 @@ arrays which are defined at the beginning of `keyboard.c`
|
|||||||
- When the OS wants to read user input, it calls `libc/io.c:readline()`
|
- When the OS wants to read user input, it calls `libc/io.c:readline()`
|
||||||
|
|
||||||
`keyboard.c` also parses backspace, by removing the last element
|
`keyboard.c` also parses backspace, by removing the last element
|
||||||
of the key buffer, and deleting it from the screen, by calling
|
of the key buffer, and deleting it from the screen, by calling
|
||||||
`screen.c:kprint_backspace()`. For this we needed to modify a bit
|
`screen.c:kprint_backspace()`. For this we needed to modify a bit
|
||||||
`print_char()` to not advance the offset when printing a backspace
|
`print_char()` to not advance the offset when printing a backspace
|
||||||
|
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
|
malloc
|
||||||
|
======
|
||||||
|
|
||||||
*Concepts you may want to Google beforehand: malloc*
|
*Concepts you may want to Google beforehand: malloc*
|
||||||
|
|
||||||
**Goal: Implement a memory allocator**
|
**Goal: Implement a memory allocator**
|
||||||
|
|
||||||
We will add a kernel memory allocator to `libc/mem.c`. It is
|
We will add a kernel memory allocator to `libc/mem.c`. It is
|
||||||
implemented as a simple pointer to free memory, which keeps
|
implemented as a simple pointer to free memory, which keeps
|
||||||
growing.
|
growing.
|
||||||
|
|
||||||
@ -18,7 +21,7 @@ aligned 4096 bytes or 0x1000 from the previous one.
|
|||||||
Note that we added a new `strings.c:hex_to_ascii()` for
|
Note that we added a new `strings.c:hex_to_ascii()` for
|
||||||
nicer printing of hex numbers.
|
nicer printing of hex numbers.
|
||||||
|
|
||||||
Another cosmetic modification is to rename `types.c` to
|
Another cosmetic modification is to rename `types.c` to
|
||||||
`type.c` for language consistency.
|
`type.c` for language consistency.
|
||||||
|
|
||||||
The rest of the files are unchanged from last lesson.
|
The rest of the files are unchanged from last lesson.
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
Fixes
|
||||||
|
=====
|
||||||
|
|
||||||
*Concepts you may want to Google beforehand: freestanding, uint32_t, size_t*
|
*Concepts you may want to Google beforehand: freestanding, uint32_t, size_t*
|
||||||
|
|
||||||
**Goal: Fix miscellaneous issues with our code**
|
**Goal: Fix miscellaneous issues with our code**
|
||||||
@ -22,7 +25,7 @@ it for linking. Since this is tricky, we'll delete `-nostdlib`
|
|||||||
2. kernel.c `main()` function
|
2. kernel.c `main()` function
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
|
||||||
Modify `kernel/kernel.c` and change `main()` to `kernel_main()` since gcc recognizes "main" as
|
Modify `kernel/kernel.c` and change `main()` to `kernel_main()` since gcc recognizes "main" as
|
||||||
a special keyword and we don't want to mess with that.
|
a special keyword and we don't want to mess with that.
|
||||||
|
|
||||||
Change `boot/kernel_entry.asm` to point to the new name accordingly.
|
Change `boot/kernel_entry.asm` to point to the new name accordingly.
|
||||||
@ -48,7 +51,7 @@ We also delete the underscores around `__asm__` and `__volatile__` since they ar
|
|||||||
|
|
||||||
First, since `kmalloc` uses a size parameter, we'll use the correct data type `size_t` instead
|
First, since `kmalloc` uses a size parameter, we'll use the correct data type `size_t` instead
|
||||||
of `u32int_t`. `size_t` should be used for all parameters which "count" stuff and cannot be
|
of `u32int_t`. `size_t` should be used for all parameters which "count" stuff and cannot be
|
||||||
negative. Include `<stddef.h>`.
|
negative. Include `<stddef.h>`.
|
||||||
|
|
||||||
We will fix our `kmalloc` in the future, making it a proper memory manager and aligning data types.
|
We will fix our `kmalloc` in the future, making it a proper memory manager and aligning data types.
|
||||||
For now, it will always return a new page-aligned memory block.
|
For now, it will always return a new page-aligned memory block.
|
||||||
@ -65,12 +68,12 @@ We will implement the missing `mem*` functions in following lessons
|
|||||||
`cli` is redundant, since we already established on the IDT entries if interrupts
|
`cli` is redundant, since we already established on the IDT entries if interrupts
|
||||||
are enabled within a handler using the `idt_gate_t` flags.
|
are enabled within a handler using the `idt_gate_t` flags.
|
||||||
|
|
||||||
`sti` is also redundant, as `iret` loads the eflags value from the stack, which contains a
|
`sti` is also redundant, as `iret` loads the eflags value from the stack, which contains a
|
||||||
bit telling whether interrupts are on or off.
|
bit telling whether interrupts are on or off.
|
||||||
In other words the interrupt handler automatically restores interrupts whether or not
|
In other words the interrupt handler automatically restores interrupts whether or not
|
||||||
interrupts were enabled before this interrupt
|
interrupts were enabled before this interrupt
|
||||||
|
|
||||||
On `cpu/isr.h`, `struct registers_t` has a couple issues.
|
On `cpu/isr.h`, `struct registers_t` has a couple issues.
|
||||||
First, the alleged `esp` is renamed to `useless`.
|
First, the alleged `esp` is renamed to `useless`.
|
||||||
The value is useless because it has to do with the current stack context, not what was interrupted.
|
The value is useless because it has to do with the current stack context, not what was interrupted.
|
||||||
Then, we rename `useresp` to `esp`
|
Then, we rename `useresp` to `esp`
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
El Capitan
|
||||||
|
==========
|
||||||
|
|
||||||
**Goal: Update our build system to El Capitan**
|
**Goal: Update our build system to El Capitan**
|
||||||
|
|
||||||
If you were following this guide from the beginning and upgraded to El Capitan only
|
If you were following this guide from the beginning and upgraded to El Capitan only
|
||||||
@ -56,10 +59,10 @@ tar xf gcc-4.9.1.tar.bz2
|
|||||||
mkdir gcc-build
|
mkdir gcc-build
|
||||||
cd gcc-build
|
cd gcc-build
|
||||||
../gcc-4.9.1/configure --target=$TARGET --prefix="$PREFIX" --disable-nls --disable-libssp --enable-languages=c --without-headers
|
../gcc-4.9.1/configure --target=$TARGET --prefix="$PREFIX" --disable-nls --disable-libssp --enable-languages=c --without-headers
|
||||||
make all-gcc
|
make all-gcc
|
||||||
make all-target-libgcc
|
make all-target-libgcc
|
||||||
make install-gcc
|
make install-gcc
|
||||||
make install-target-libgcc
|
make install-target-libgcc
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
191
pandoc.context
Normal file
191
pandoc.context
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
$if(context-lang)$
|
||||||
|
\mainlanguage[$context-lang$]
|
||||||
|
$endif$
|
||||||
|
$if(context-dir)$
|
||||||
|
\setupalign[$context-dir$]
|
||||||
|
\setupdirections[bidi=on,method=two]
|
||||||
|
$endif$
|
||||||
|
% Enable hyperlinks
|
||||||
|
\setupinteraction
|
||||||
|
[state=start,
|
||||||
|
$if(title)$
|
||||||
|
title={$title$},
|
||||||
|
$endif$
|
||||||
|
$if(subtitle)$
|
||||||
|
subtitle={$subtitle$},
|
||||||
|
$endif$
|
||||||
|
$if(author)$
|
||||||
|
author={$for(author)$$author$$sep$; $endfor$},
|
||||||
|
$endif$
|
||||||
|
$if(keywords)$
|
||||||
|
keyword={$for(keywords)$$keywords$$sep$; $endfor$},
|
||||||
|
$endif$
|
||||||
|
style=$linkstyle$,
|
||||||
|
color=$linkcolor$,
|
||||||
|
contrastcolor=$linkcontrastcolor$]
|
||||||
|
\setupurl[style=$urlstyle$]
|
||||||
|
|
||||||
|
% make chapter, section bookmarks visible when opening document
|
||||||
|
\placebookmarks[chapter, section, subsection, subsubsection, subsubsubsection, subsubsubsubsection][chapter, section]
|
||||||
|
\setupinteractionscreen[option={bookmark,title}]
|
||||||
|
|
||||||
|
$if(papersize)$
|
||||||
|
\setuppapersize[$for(papersize)$$papersize$$sep$,$endfor$]
|
||||||
|
$endif$
|
||||||
|
$if(layout)$
|
||||||
|
\setuplayout[$for(layout)$$layout$$sep$,$endfor$]
|
||||||
|
$endif$
|
||||||
|
$if(pagenumbering)$
|
||||||
|
\setuppagenumbering[$for(pagenumbering)$$pagenumbering$$sep$,$endfor$]
|
||||||
|
$else$
|
||||||
|
\setuppagenumbering[location={footer,middle}]
|
||||||
|
$endif$
|
||||||
|
$if(pdfa)$
|
||||||
|
% attempt to generate PDF/A
|
||||||
|
\setupbackend
|
||||||
|
[format=PDF/A-$pdfa$,
|
||||||
|
profile={$if(pdfaiccprofile)$$for(pdfaiccprofile)$$pdfaiccprofile$$sep$,$endfor$$else$sRGB.icc$endif$},
|
||||||
|
intent=$if(pdfaintent)$$pdfaintent$$else$sRGB IEC61966-2.1$endif$]
|
||||||
|
$endif$
|
||||||
|
\setupbackend[export=yes]
|
||||||
|
\setupstructure[state=start,method=auto]
|
||||||
|
|
||||||
|
% use microtypography
|
||||||
|
\definefontfeature[default][default][script=latn, protrusion=quality, expansion=quality, itlc=yes, textitalics=yes, onum=yes, pnum=yes]
|
||||||
|
\definefontfeature[default:tnum][default][tnum=yes, pnum=no]
|
||||||
|
\definefontfeature[smallcaps][script=latn, protrusion=quality, expansion=quality, smcp=yes, onum=yes, pnum=yes]
|
||||||
|
\setupalign[hz,hanging]
|
||||||
|
\setupitaliccorrection[global, always]
|
||||||
|
|
||||||
|
\setupbodyfontenvironment[default][em=italic] % use italic as em, not slanted
|
||||||
|
|
||||||
|
\definefallbackfamily[mainface][rm][CMU Serif][preset=range:greek, force=yes]
|
||||||
|
\definefontfamily[mainface][rm][$if(mainfont)$$mainfont$$else$Latin Modern Roman$endif$]
|
||||||
|
\definefontfamily[mainface][mm][$if(mathfont)$$mathfont$$else$Latin Modern Math$endif$]
|
||||||
|
\definefontfamily[mainface][ss][$if(sansfont)$$sansfont$$else$Latin Modern Sans$endif$]
|
||||||
|
\definefontfamily[mainface][tt][$if(monofont)$$monofont$$else$Latin Modern Typewriter$endif$][features=none]
|
||||||
|
\setupbodyfont[mainface$if(fontsize)$,$fontsize$$endif$]
|
||||||
|
|
||||||
|
\setupwhitespace[$if(whitespace)$$whitespace$$else$medium$endif$]
|
||||||
|
$if(indenting)$
|
||||||
|
\setupindenting[$for(indenting)$$indenting$$sep$,$endfor$]
|
||||||
|
$endif$
|
||||||
|
$if(interlinespace)$
|
||||||
|
\setupinterlinespace[$for(interlinespace)$$interlinespace$$sep$,$endfor$]
|
||||||
|
$endif$
|
||||||
|
|
||||||
|
\setuphead[chapter] [style=\tfd\setupinterlinespace,header=empty]
|
||||||
|
\setuphead[section] [style=\tfc\setupinterlinespace]
|
||||||
|
\setuphead[subsection] [style=\tfb\setupinterlinespace]
|
||||||
|
\setuphead[subsubsection] [style=\bf]
|
||||||
|
\setuphead[subsubsubsection] [style=\sc]
|
||||||
|
\setuphead[subsubsubsubsection][style=\it]
|
||||||
|
|
||||||
|
\definesectionlevels
|
||||||
|
[default]
|
||||||
|
[section, subsection, subsubsection, subsubsubsection, subsubsubsubsection]
|
||||||
|
|
||||||
|
$if(headertext)$
|
||||||
|
\setupheadertexts$for(headertext)$[$headertext$]$endfor$
|
||||||
|
$endif$
|
||||||
|
$if(footertext)$
|
||||||
|
\setupfootertexts$for(footertext)$[$footertext$]$endfor$
|
||||||
|
$endif$
|
||||||
|
$if(number-sections)$
|
||||||
|
$else$
|
||||||
|
\setuphead[chapter, section, subsection, subsubsection, subsubsubsection, subsubsubsubsection][number=no]
|
||||||
|
$endif$
|
||||||
|
|
||||||
|
\definedescription
|
||||||
|
[description]
|
||||||
|
[headstyle=bold, style=normal, location=hanging, width=broad, margin=1cm, alternative=hanging]
|
||||||
|
|
||||||
|
\setupitemize[autointro] % prevent orphan list intro
|
||||||
|
\setupitemize[indentnext=no]
|
||||||
|
|
||||||
|
\defineitemgroup[enumerate]
|
||||||
|
\setupenumerate[each][fit][itemalign=left,distance=.5em,style={\feature[+][default:tnum]}]
|
||||||
|
|
||||||
|
\setupfloat[figure][default={here,nonumber}]
|
||||||
|
\setupfloat[table][default={here,nonumber}]
|
||||||
|
|
||||||
|
\setupxtable[frame=off]
|
||||||
|
\setupxtable[head][topframe=on]
|
||||||
|
\setupxtable[body][]
|
||||||
|
\setupxtable[foot][]
|
||||||
|
\setupxtable[lastrow][bottomframe=on]
|
||||||
|
|
||||||
|
$if(emphasis-commands)$
|
||||||
|
$emphasis-commands$
|
||||||
|
$endif$
|
||||||
|
$if(highlighting-commands)$
|
||||||
|
$highlighting-commands$
|
||||||
|
$endif$
|
||||||
|
$if(csl-refs)$
|
||||||
|
\definemeasure[cslhangindent][1.5em]
|
||||||
|
\definenarrower[hangingreferences][left=\measure{cslhangindent}]
|
||||||
|
\definestartstop [cslreferences] [
|
||||||
|
$if(csl-hanging-indent)$
|
||||||
|
before={%
|
||||||
|
\starthangingreferences[left]
|
||||||
|
\setupindenting[-\leftskip,yes,first]
|
||||||
|
\doindentation
|
||||||
|
},
|
||||||
|
after=\stophangingreferences,
|
||||||
|
$endif$
|
||||||
|
]
|
||||||
|
$endif$
|
||||||
|
$if(includesource)$
|
||||||
|
$for(sourcefile)$
|
||||||
|
\attachment[file=$curdir$/$sourcefile$,method=hidden]
|
||||||
|
$endfor$
|
||||||
|
$endif$
|
||||||
|
$for(header-includes)$
|
||||||
|
$header-includes$
|
||||||
|
$endfor$
|
||||||
|
|
||||||
|
\starttext
|
||||||
|
$if(title)$
|
||||||
|
\startalignment[middle]
|
||||||
|
{\tfd\setupinterlinespace $title$}
|
||||||
|
$if(subtitle)$
|
||||||
|
\smallskip
|
||||||
|
{\tfa\setupinterlinespace $subtitle$}
|
||||||
|
$endif$
|
||||||
|
$if(author)$
|
||||||
|
\smallskip
|
||||||
|
{\tfa\setupinterlinespace $for(author)$$author$$sep$\crlf $endfor$}
|
||||||
|
$endif$
|
||||||
|
$if(date)$
|
||||||
|
\smallskip
|
||||||
|
{\tfa\setupinterlinespace $date$}
|
||||||
|
$endif$
|
||||||
|
\bigskip
|
||||||
|
\stopalignment
|
||||||
|
$endif$
|
||||||
|
$if(abstract)$
|
||||||
|
\midaligned{\it Abstract}
|
||||||
|
\startnarrower[2*middle]
|
||||||
|
$abstract$
|
||||||
|
\stopnarrower
|
||||||
|
\blank[big]
|
||||||
|
$endif$
|
||||||
|
$for(include-before)$
|
||||||
|
$include-before$
|
||||||
|
$endfor$
|
||||||
|
$if(toc)$
|
||||||
|
\completecontent
|
||||||
|
$endif$
|
||||||
|
$if(lof)$
|
||||||
|
\completelistoffigures
|
||||||
|
$endif$
|
||||||
|
$if(lot)$
|
||||||
|
\completelistoftables
|
||||||
|
$endif$
|
||||||
|
|
||||||
|
$body$
|
||||||
|
|
||||||
|
$for(include-after)$
|
||||||
|
$include-after$
|
||||||
|
$endfor$
|
||||||
|
\stoptext
|
52
pandoc.yaml
Normal file
52
pandoc.yaml
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
from: gfm
|
||||||
|
input-files:
|
||||||
|
- ${.}/README.md
|
||||||
|
- ${.}/00-environment/README.md
|
||||||
|
- ${.}/01-bootsector-barebones/README.md
|
||||||
|
- ${.}/02-bootsector-print/README.md
|
||||||
|
- ${.}/03-bootsector-memory/README.md
|
||||||
|
- ${.}/04-bootsector-stack/README.md
|
||||||
|
- ${.}/05-bootsector-functions-strings/README.md
|
||||||
|
- ${.}/06-bootsector-segmentation/README.md
|
||||||
|
- ${.}/07-bootsector-disk/README.md
|
||||||
|
- ${.}/08-32bit-print/README.md
|
||||||
|
- ${.}/09-32bit-gdt/README.md
|
||||||
|
- ${.}/10-32bit-enter/README.md
|
||||||
|
- ${.}/11-kernel-crosscompiler/README.md
|
||||||
|
- ${.}/12-kernel-c/README.md
|
||||||
|
- ${.}/13-kernel-barebones/README.md
|
||||||
|
- ${.}/14-checkpoint/README.md
|
||||||
|
- ${.}/15-video-ports/README.md
|
||||||
|
- ${.}/16-video-driver/README.md
|
||||||
|
- ${.}/17-video-scroll/README.md
|
||||||
|
- ${.}/18-interrupts/README.md
|
||||||
|
- ${.}/19-interrupts-irqs/README.md
|
||||||
|
- ${.}/20-interrupts-timer/README.md
|
||||||
|
- ${.}/21-shell/README.md
|
||||||
|
- ${.}/22-malloc/README.md
|
||||||
|
- ${.}/23-fixes/README.md
|
||||||
|
- ${.}/24-el-capitan/README.md
|
||||||
|
|
||||||
|
to: pdf
|
||||||
|
pdf-engine: context
|
||||||
|
output-file: os-tutorial.pdf
|
||||||
|
|
||||||
|
variables:
|
||||||
|
title: OS Tutorial
|
||||||
|
subtitle: How to create an OS from scratch
|
||||||
|
author: Carlos Fenollosa
|
||||||
|
includesource: true
|
||||||
|
papersize: letter
|
||||||
|
pdfa: true
|
||||||
|
linkcolor: blue
|
||||||
|
linkcontrastcolor: red
|
||||||
|
|
||||||
|
file-scope: true
|
||||||
|
verbosity: ERROR
|
||||||
|
tab-stop: 4
|
||||||
|
template: ./pandoc.context
|
||||||
|
dpi: 300
|
||||||
|
toc: true
|
||||||
|
top-level-division: chapter
|
||||||
|
reference-location: section
|
||||||
|
number-sections: true
|
Loading…
Reference in New Issue
Block a user