diff --git a/course/01-Boot_grub.md b/course/01-Boot_grub.md new file mode 100644 index 0000000000000000000000000000000000000000..fa71f31652fec656221db8a2859df1c495931ee1 --- /dev/null +++ b/course/01-Boot_grub.md @@ -0,0 +1,396 @@ +--- +author: Florent Gluck - Florent.Gluck@hesge.ch + +title: Boot process and GRUB + +date: \vspace{.5cm} \footnotesize \today + +pandoc-latex-fontsize: + - classes: [tiny] + size: tiny + - classes: [verysmall] + size: scriptsize + - classes: [small] + size: footnotesize + - classes: [huge, important] + size: huge +--- + +[//]: # ---------------------------------------------------------------- +# Boot process + +[//]: # ---------------------------------------------------------------- +## Boot loader + +- **Purpose of a bootloader**: + - basic hardware initialization + - loading of an application binary, usually a kernel from storage, network, etc. + - execution of the binary + +\vspace{.3cm} + +- Most bootloaders provide a shell with various commands: + - loading data from storage or network, memory inspection, boot kernel, hardware diagnostics, etc. + +[//]: # ---------------------------------------------------------------- +## BIOS and UEFI + +- **BIOS** (Basic Input/Output System) is the old historical PC firmware + - executed in 16-bit mode (*real mode*) with 1MB of address space + - very basic services and only usable in 16-bit mode + +\vspace{.3cm} + +- **UEFI** (Unified Extensible Firmware Interface) is BIOS' successor + - executed in either 32 or 64-bit mode + - features many services and modules + - highly complex (specs are 4k+ page long) + - BIOS-compatible mode called *legacy mode* + +\vspace{.3cm} +- BIOS and UEFI are stored in non-volatile memory (e.g. flash) + +<!-- +[//]: # ---------------------------------------------------------------- +## BIOS boot process stages (x86) + +:::::: {.columns} +::: {.column width="70%"} + +\small + +\vspace{.8cm} + +1. BIOS is executed after reset $\rightarrow$ responsible for basic hardware initialization +1. Searches for a bootable device by loading the first sector (512 bytes) of each storage device until finding a valid signature: `0x55AA` at offset 510 +1. This 510 bytes code is usually the "stage1" bootloader which loads "stage2" +1. "stage2" is much larger, switches CPU to 32-bit mode and typically understands filesystems so kernel can be loaded directly from a filesystem + +::: +::: {.column width="30%"} + +\centering +{ width=80% } + +::: +:::::: +--> + +[//]: # ---------------------------------------------------------------- +## UEFI boot process (x86) + +- UEFI loads and executes an arbitrary sized UEFI application from an EFI System Partition (ESP) + - This application must reside in a certain location in the filesystem e.g. `/efi/BOOT/BOOTX64.EFI` on a x86-64 PC +- An UEFI-compliant boot device must have a GUID Partition Table (GPT) that specifies an ESP + - This ESP must be formatted with the FAT filesystem +- UEFI can boot in "legacy mode" to boot on legacy software written for BIOS + +<!-- +[//]: # ---------------------------------------------------------------- +## MBR partition table (BIOS) + +{ width=100% } + +\vfill +\tiny +Source: [\textcolor{myblue}{https://en.wikipedia.org/wiki/Master\_boot\_record}](https://en.wikipedia.org/wiki/Master_boot_record) + +[//]: # ---------------------------------------------------------------- +## GUID partition table (UEFI) + +\centering +{ width=90% } + +\vfill +\tiny +\centering +Source: [\textcolor{myblue}{http://www.ntfs.com/guid-part-table.htm}](http://www.ntfs.com/guid-part-table.htm) +--> + +[//]: # ---------------------------------------------------------------- +# GRUB + +[//]: # ---------------------------------------------------------------- +## Multiboot specification + +- Open specification defining how a bootloader may load a kernel + +- **Goals** + - Allow any bootloader to load any compatible OS $\rightarrow$ guarantee **interoperability** + - Allow to boot **multiple** OS on the same machine + +- Reference: \footnotesize [\textcolor{myblue}{https://www.gnu.org/software/grub/manual/multiboot/multiboot.html}](https://www.gnu.org/software/grub/manual/multiboot/multiboot.html) + +[//]: # ---------------------------------------------------------------- +## The “**GR**and **U**nified **B**ootloader” (GRUB) + +- GRUB is a powerful and versatile bootloader able to boot multiple OS +- Implements the multiboot specification +- Features: + - shell allowing user interaction + - on-the-fly changes to the boot configuration + - ability to load modules at runtime to extend its capabilities + - configuration file (`grub.cfg`) to configure its behavior +- Open source GNU project (GPL 3.0 license) +- Latest version is GRUB 2 + +[//]: # ---------------------------------------------------------------- +## GRUB boot process + +\small + +GRUB is a *chain bootloader* $\rightarrow$ multiple stage initialization: + +- **Stage1**: located in sector 0, loaded in RAM by BIOS/UEFI + - \footnotesize stage1 image usually in `/boot/grub/i386-pc/boot.img` + - contains code required to load stage2 + +\vspace{.3cm} + +- **Stage2**: max 32KB, located in first sectors, loaded by stage1 + - \footnotesize stage2 image usually in `/boot/grub/i386-pc/core.img` + - contains drivers required to access the filesystem (`/boot/grub/grub.cfg`, grub modules, kernel image) + - displays the GRUB menu interface and command prompt + - able to load an OS **located on a filesystem** + +[//]: # ---------------------------------------------------------------- +## Example: Linux kernel boot process + +\centering +{ width=95% } + +[//]: # ---------------------------------------------------------------- +## System state at boot + +- GRUB switches CPU to 32-bit (protected mode) + +- GRUB initializes CPU and its own GDT (memory mapping) + + - See “Machine state” in multiboot specification: \tiny [\textcolor{myblue}{https://www.gnu.org/software/grub/manual/multiboot/multiboothtml\#Machine-state}](https://www.gnu.org/software/grub/manual/multiboot/multiboothtml#Machine-state) + +- \normalsize GRUB stores in `EBX` register, the address of a structure containing info detected at boot time (RAM, etc.) and GRUB info (modules, cmd line, etc.) + - This structure is `multiboot_info_t` and is defined in `multiboot.h` + - Content of `multiboot.h`: \tiny [\textcolor{myblue}{http://git.savannah.gnu.org/cgit/grub.git/tree/doc/multiboot.h?h=multiboot}](http://git.savannah.gnu.org/cgit/grub.git/tree/doc/multiboot.h?h=multiboot) + +[//]: # ---------------------------------------------------------------- +## Example of "empty" bootstrap code loaded by GRUB + +```{.tiny .assembler} +; Values for the multiboot header +MULTIBOOT_MAGIC equ 0x1BADB002 ; multiboot magic value +MULTIBOOT_ALIGN equ 1 ; load kernel and modules on page boundary +MULTIBOOT_MEMINFO equ 2 ; provide kernel with memory info + +MULTIBOOT_FLAGS equ (MULTIBOOT_ALIGN|MULTIBOOT_MEMINFO) + +; Magic + checksum + flags must equal 0! +MULTIBOOT_CHECKSUM equ -(MULTIBOOT_MAGIC + MULTIBOOT_FLAGS) + +section .multiboot + +; Mandatory part of the multiboot header +dd MULTIBOOT_MAGIC +dd MULTIBOOT_FLAGS +dd MULTIBOOT_CHECKSUM + +entrypoint: + ; Bootloader code starts executing here + cli ; disable hardware interrupts + +.forever: + hlt + jmp .forever +``` + +[//]: # ---------------------------------------------------------------- +## Booting on a custom OS + +::: incremental + +How to boot on a custom OS? + +- Easiest way is to store the OS in a ISO image +- ISO 9660 is a filesystem standard designed for optical disks (CD-ROM, DVD-ROM, etc.) +- ISO 9660 image = image of a read-only filesystem to be stored on a CD-ROM to be booted on +- An ISO image can be "flashed" on a USB key (e.g. with `dd`) to make it bootable +- For an ISO image to be bootable, GRUB must be installed in the first sectors (in the first 8KB) + +::: + +[//]: # ---------------------------------------------------------------- +## ISO image generation + +\footnotesize + +How to create an ISO image bootable with GRUB and containing `kernel.elf`? + +\vspace{.2cm} + +:::::: {.columns} +::: {.column width="40%"} + +Prepare this file structure: +```{.verysmall} +build/ +`-- boot + |-- grub + | `-- grub.cfg + `-- kernel.elf +``` + +::: +::: {.column width="50%"} + +Content of `grub.cfg`: +```{.verysmall} +set timeout=1 + +menuentry "MyOS" { + multiboot /boot/kernel.elf +} +``` + +::: +:::::: + +- Where: + - `build` is the root directory used for the ISO image + - `grub.cfg` is the GRUB configuration + - `kernel.elf` is the kernel to boot + +- To create the `myos.iso` image, run: + ```{.verysmall} + grub-mkrescue /usr/lib/grub/i386-pc -o myos.iso build + ``` + +[//]: # ---------------------------------------------------------------- +## Required Ubuntu packages + +To run `grub-mkrescue` on a Ubuntu system, the following packages are **required**: + +- `grub-common` +- `grub-pc-bin` +- `xorriso` +- `mtools` + +[//]: # ---------------------------------------------------------------- +## Multiboot boot modules + +- The multiboot specification allows a bootloader to automatically load arbitrary files into memory (RAM) +- These files are called "boot modules" + - they can have a command line, retrievable by the kernel +- GRUB can automatically load such boot modules into RAM +- Each file's content can then be addressed by the kernel +- The kernel only needs to know: + - at which address a boot module is loaded + - the module's length + - if needed: the module's command line +- Luckily, these information are provided by GRUB! + +[//]: # ---------------------------------------------------------------- +## Boot modules example + +Below, we tells GRUB to load 2 boot modules: `prog` and `logo.png`: + +\vspace{.2cm} + +:::::: {.columns} +::: {.column width="50%"} + +```{.verysmall} +set timeout=1 + +menuentry "MyOS" { + multiboot /boot/kernel.elf + module /bin/prog arg1 arg2 + module /data/logo.png +} +``` + +::: +::: {.column width="40%"} + +```{.verysmall} +build/ +`-- boot + | |-- grub + | | `-- grub.cfg + | `-- kernel.elf + |--bin + | `-- prog + `--data + `-- logo.png +``` + +::: +:::::: + +[//]: # ---------------------------------------------------------------- +## Multiboot structure + +- The multiboot specification defines a set of information that can be retrieved by the kernel (or any executable binary loaded by the bootloader) +- These information are stored in the `multiboot_info_t` structure defined in `multiboot.h` +- Examples of information available in the structure: + - RAM available on the system + - kernel command line + - number of boot modules + - address and length of each boot module + - framebuffer address + - horizontal display resolution + - etc. + +[//]: # ---------------------------------------------------------------- +## Multiboot structure: important remarks + +- Many `multiboot_info_t` fields are defined as `multiboot_uint32_t` +- However, often they simply represent 32-bit addresses (since the CPU is in 32-bit mode, addresses are 32 bits long) +- Reminder: + - if a CPU uses 32 bits addresses, then a 32-bit integer can be used as an address + - in C, the value of a pointer is an address, thus an integer +- Therefore, it's up to you to cast these 32-bit integers to whatever pointer type is needed + +[//]: # ---------------------------------------------------------------- +## Boot modules information (1/2) + +- The `multiboot_info_t` structure stores everything about boot modules in these members: + - `mods_count`: number of boot modules loaded by GRUB + - `mods_addr`: address of the first loaded module; this member is of the type `(multiboot_module_t *)` + +\vspace{.3cm} + +- Then, for each module (of type `multiboot_module_t *`): + - `mod_start`: address where the module content starts (inclusive) + - `mod_end`: address where the module content ends (non-inclusive) + - The memory content range of the module is then: `[mod_start, mod_end[` + - `cmdline`: address of the module command line (`"arg1 arg2"` for module `prog` in the previous example) + +[//]: # ---------------------------------------------------------------- +## Boot modules information (2/2) + +- `mods_addr` can be seen as an array of `multiboot_module_t` elements +- The size of this array is `mods_count` +- Each module's command line is simply a C string, thus an address pointing to the first character of the command line + - the end of the command line is marked with the value 0 + +[//]: # ---------------------------------------------------------------- +## Resources + +\small + +- Booting Linux on x86 using Grub2\ +\footnotesize [\textcolor{myblue}{http://moi.vonos.net/linux/Booting\_Linux\_on\_x86\_with\_Grub2/}](http://moi.vonos.net/linux/Booting_Linux_on_x86_with_Grub2/) + +\small + +- Multiboot2 Specification version 2.0\ +\footnotesize [\textcolor{myblue}{https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html}](https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html) + +\small + +- GNU GRUB Manual 2.04\ +\footnotesize [\textcolor{myblue}{https://www.gnu.org/software/grub/manual/grub/grub.html}](https://www.gnu.org/software/grub/manual/grub/grub.html) + +\small + +- GRUB 2 on a lower level\ +\footnotesize [\textcolor{myblue}{http://www.dolda2000.com/~fredrik/doc/grub2}](http://www.dolda2000.com/~fredrik/doc/grub2) diff --git a/course/02-VBE_display.md b/course/02-VBE_display.md new file mode 100644 index 0000000000000000000000000000000000000000..ad9c7da52d19076320c60621a8f8c46c899f528b --- /dev/null +++ b/course/02-VBE_display.md @@ -0,0 +1,166 @@ +--- +author: Florent Gluck - Florent.Gluck@hesge.ch + +title: VBE Display + +date: \vspace{.5cm} \footnotesize \today + +pandoc-latex-fontsize: + - classes: [tiny] + size: tiny + - classes: [verysmall] + size: scriptsize + - classes: [small] + size: footnotesize + - classes: [huge, important] + size: huge +--- + +[//]: # ---------------------------------------------------------------- +## PC graphics history + +:::::: {.columns} +::: {.column width="70%"} + +\small + +- Original PC didn't feature any graphics mode: only character display (text) + - Most popular: VGA text mode: 80 col. by 25 rows, 16 colors +- Over time, many graphics cards developped + - CGA ('81), EGA, VGA ('87), SVGA, etc. +- No GPU back then, everything done by CPU + - First mainsteam GPU: 3dfx Voodoo ('95) +- Every graphics card is programmed differently $\rightarrow$ very demanding + - Modern GPU are incredibly more complex and difficult to program + +::: +::: {.column width="30%"} + +\vspace{.1cm} +{ width=100% } +{ width=100% } +{ width=100% } + +::: +:::::: + +[//]: # ---------------------------------------------------------------- +## PC graphics today + +- For **compatibility reasons**, all modern PCs' graphics cards still support: + - VGA text mode + - VGA graphics modes (320x200 8bpp, 640x480 4bpp) + - Easy to program VGA text mode and VGA graphics modes + - but very dated... +- Anything higher resolution and bit depth is hardware dependent +- That's where VESA BIOS Extensions comes in + +[//]: # ---------------------------------------------------------------- +## VESA BIOS Extensions (VBE) + +- Goal was to provide a **hardware-independent** way of accessing graphics cards +- VBE is a **standard** that defines the interface to access video cards at high resolutions and bit depths + - typically 640x480, 800x600, 1024x768, 1280x1024 in 8bpp, 16bpp, 24bpp and 32bpp + - provide access to hardware accelerated features (scrolling, sprites, blitter, drawing, etc.) +- However, VBE can be very **tricky to initialize** +- Luckily... + +[//]: # ---------------------------------------------------------------- +## GRUB to the rescue + +- Multiboot bootloaders (such as GRUB) implement VBE 3.0 graphics initialization +- We can specify a *preferred* video mode +- However, no guarantee: the bootloader might use a different video mode +- The multiboot structure features details about the graphics mode set by the bootloader + +[//]: # ---------------------------------------------------------------- +## Example of bootloader requesting video mode + +\fontsize{6}{6} +```{.assembler} +MULTIBOOT_MAGIC equ 0x1BADB002 ; multiboot magic value +MULTIBOOT_ALIGN equ 1 ; load kernel and modules on page boundary +MULTIBOOT_MEMINFO equ 2 ; provide kernel with memory info +MULTIBOOT_VIDEO_MODE equ 4 ; ask grub to switch to VBE graphics modes + +MULTIBOOT_FLAGS equ (MULTIBOOT_ALIGN|MULTIBOOT_MEMINFO|MULTIBOOT_VIDEO_MODE) +MULTIBOOT_CHECKSUM equ -(MULTIBOOT_MAGIC + MULTIBOOT_FLAGS) + +section .multiboot + +; Mandatory part of the multiboot header +dd MULTIBOOT_MAGIC +dd MULTIBOOT_FLAGS +dd MULTIBOOT_CHECKSUM + +; for MULTIBOOT_MEMORY_INFO +dq 0x0000000000000000 ; header_addr + load_addr +dq 0x0000000000000000 ; load_end_addr + bss_end_addr +dd 0x00000000 ; entry_addr + +; for MULTIBOOT_VIDEO_MODE +dd 0x00000000 ; mode_type +dd 1024 ; width +dd 768 ; height +dd 32 ; depth + +entrypoint: + cli ; disable hardware interrupts + +.forever: + hlt + jmp .forever +``` + +[//]: # ---------------------------------------------------------------- +## Multiboot structure: major video mode fields + +| **Field** | **Description** | +|--- |--- | +| `framebuffer_addr` | physical address of the framebuffer | +| `framebuffer_pitch` | framebuffer pitch in **bytes** | +| `framebuffer_width` | framebuffer width in **pixels** | +| `framebuffer_height` | framebuffer height in **pixels** | +| `framebuffer_bpp` | number of **bits** per pixel | + +Note: here, we ignore palletized video modes (typically 8bpp). + +[//]: # ---------------------------------------------------------------- +## Framebuffer layout + +\centering +{ width=95% } + +\vspace{.2cm} + +\scriptsize +**Beware**: `framebuffer_pitch` is in **bytes** whereas `framebuffer_width` is in **pixels**! + +[//]: # ---------------------------------------------------------------- +## Pixel addressing + +- \textcolor{myred}{We must \textbf{always} use the pitch to calculate the pixel address, not the width!} +- How to convert a 2D pixel position into a 1D memory address? +- General formula, given a position (x,y) in pixels: + ```{.small} + pixel_address = framebuffer_address + y * pitch_in_pixels + x + ``` + Beware: above, pitch is in pixels, not in bytes! + +[//]: # ---------------------------------------------------------------- +## Resources + +- VESA BIOS Extensions on Wikipedia\ +\scriptsize [\textcolor{myblue}{https://en.wikipedia.org/wiki/VESA\_BIOS\_Extensions}](https://en.wikipedia.org/wiki/VESA_BIOS_Extensions) + +\normalsize +\vspace{.3cm} + +- VBE 3.0 specification\ +\scriptsize [\textcolor{myblue}{http://www.petesqbsite.com/sections/tutorials/tuts/vbe3.pdf}](http://www.petesqbsite.com/sections/tutorials/tuts/vbe3.pdf) + +\normalsize +\vspace{.3cm} + +- Multiboot Specification: Boot information format\ +\scriptsize [\textcolor{myblue}{https://www.gnu.org/software/grub/manual/multiboot/multiboot.html\#Boot-information-format}](https://www.gnu.org/software/grub/manual/multiboot/multiboot.html#Boot-information-format) diff --git a/course/Makefile b/course/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..63e44b47887cff306d9fe961b09f0554aa860649 --- /dev/null +++ b/course/Makefile @@ -0,0 +1,12 @@ +SRCS=$(wildcard *.md) +PDFS=$(SRCS:%.md=%.pdf) +UID=$(shell id -u) +GID=$(shell id -g) + +all: $(PDFS) + +%.pdf: %.md + docker run --user $(UID):$(GID) --rm --mount type=bind,src="$(PWD)",dst=/src thxbb12/md2pdf build_slides $< + +clean: + rm -f $(PDFS) diff --git a/course/images/GDT.png b/course/images/GDT.png new file mode 100644 index 0000000000000000000000000000000000000000..5d7492069254164d7a2259248ab865f6c8b8328c Binary files /dev/null and b/course/images/GDT.png differ diff --git a/course/images/PICs.png b/course/images/PICs.png new file mode 100644 index 0000000000000000000000000000000000000000..bd043c75b2d4673ca49610a68113d9dc84b59cf9 Binary files /dev/null and b/course/images/PICs.png differ diff --git a/course/images/address_space.png b/course/images/address_space.png new file mode 100644 index 0000000000000000000000000000000000000000..ca74a53a1c2666237bcc17b1347806baf765fdd6 Binary files /dev/null and b/course/images/address_space.png differ diff --git a/course/images/address_space_without_legends.png b/course/images/address_space_without_legends.png new file mode 100644 index 0000000000000000000000000000000000000000..60fe8db34bc192aa1eb11641c9a75b26b34f1667 Binary files /dev/null and b/course/images/address_space_without_legends.png differ diff --git a/course/images/address_translation_x86-64.png b/course/images/address_translation_x86-64.png new file mode 100644 index 0000000000000000000000000000000000000000..c0897153f5e68ab6be5eb836c396dbed5c6a1116 Binary files /dev/null and b/course/images/address_translation_x86-64.png differ diff --git a/course/images/basic_address_space.png b/course/images/basic_address_space.png new file mode 100644 index 0000000000000000000000000000000000000000..b159f40aec2ac566f9ad3400d29ce29599656361 Binary files /dev/null and b/course/images/basic_address_space.png differ diff --git a/course/images/context.png b/course/images/context.png new file mode 100644 index 0000000000000000000000000000000000000000..2627c73913a0c598545a637a55f0ac8be25ffdf6 Binary files /dev/null and b/course/images/context.png differ diff --git a/course/images/cpu_exceptions.png b/course/images/cpu_exceptions.png new file mode 100644 index 0000000000000000000000000000000000000000..b05e60ce758c51fb61b92aac564d26013e400ec4 Binary files /dev/null and b/course/images/cpu_exceptions.png differ diff --git a/course/images/exception_handlers.png b/course/images/exception_handlers.png new file mode 100644 index 0000000000000000000000000000000000000000..e3076611ce7a2e7b87d5c87a42648fb41c5d0020 Binary files /dev/null and b/course/images/exception_handlers.png differ diff --git a/course/images/external_fragmentation.png b/course/images/external_fragmentation.png new file mode 100644 index 0000000000000000000000000000000000000000..b78d2329091bea863b590b72e0eca9515f004fd7 Binary files /dev/null and b/course/images/external_fragmentation.png differ diff --git a/course/images/frame_management.png b/course/images/frame_management.png new file mode 100644 index 0000000000000000000000000000000000000000..5a148b6fdf237d4b137f03f52f5058b864f87eef Binary files /dev/null and b/course/images/frame_management.png differ diff --git a/course/images/frame_management_bitarray.png b/course/images/frame_management_bitarray.png new file mode 100644 index 0000000000000000000000000000000000000000..b36d7fb9a35babff84b656e72f19b5340a6a792c Binary files /dev/null and b/course/images/frame_management_bitarray.png differ diff --git a/course/images/framebuffer.png b/course/images/framebuffer.png new file mode 100644 index 0000000000000000000000000000000000000000..9568931e7997530228c456eb0a6bf62eaffa505c Binary files /dev/null and b/course/images/framebuffer.png differ diff --git a/course/images/hw_int.png b/course/images/hw_int.png new file mode 100644 index 0000000000000000000000000000000000000000..77fa1e8705cb3c797e0e1a17e0583e972ab210be Binary files /dev/null and b/course/images/hw_int.png differ diff --git a/course/images/ia32_mapping_example.png b/course/images/ia32_mapping_example.png new file mode 100644 index 0000000000000000000000000000000000000000..d88c79fcbc10915a4a76f4b2fa327b05e018cd24 Binary files /dev/null and b/course/images/ia32_mapping_example.png differ diff --git a/course/images/identity_mapping.png b/course/images/identity_mapping.png new file mode 100644 index 0000000000000000000000000000000000000000..1aff78867fda19291dcd90156edd4ae17a71fa7b Binary files /dev/null and b/course/images/identity_mapping.png differ diff --git a/course/images/idt_and_idtr.png b/course/images/idt_and_idtr.png new file mode 100644 index 0000000000000000000000000000000000000000..33fd12be5a345a0c22de2a21f0f4754e9c1dbcc0 Binary files /dev/null and b/course/images/idt_and_idtr.png differ diff --git a/course/images/interrupt_desc.png b/course/images/interrupt_desc.png new file mode 100644 index 0000000000000000000000000000000000000000..10d327f4e2a855ddf0ba70a058ea29f5bdd5346c Binary files /dev/null and b/course/images/interrupt_desc.png differ diff --git a/course/images/interrupt_handlers.png b/course/images/interrupt_handlers.png new file mode 100644 index 0000000000000000000000000000000000000000..400e8e7ced1e089dedc7c31b8f13b91ba2163112 Binary files /dev/null and b/course/images/interrupt_handlers.png differ diff --git a/course/images/interrupt_vector_table.png b/course/images/interrupt_vector_table.png new file mode 100644 index 0000000000000000000000000000000000000000..aee7722e3255c4d309553079cfd254a1d15c1680 Binary files /dev/null and b/course/images/interrupt_vector_table.png differ diff --git a/course/images/irq_global_view.png b/course/images/irq_global_view.png new file mode 100644 index 0000000000000000000000000000000000000000..423b54fb107b9c1141468c406173143597ed6c33 Binary files /dev/null and b/course/images/irq_global_view.png differ diff --git a/course/images/irq_hw_to_soft.png b/course/images/irq_hw_to_soft.png new file mode 100644 index 0000000000000000000000000000000000000000..0e10a5949eb4858d4c1973edf296b2b481f786d6 Binary files /dev/null and b/course/images/irq_hw_to_soft.png differ diff --git a/course/images/kernel_addr_space.png b/course/images/kernel_addr_space.png new file mode 100644 index 0000000000000000000000000000000000000000..1ce38dff486eec193106ca629a036b76fb514fec Binary files /dev/null and b/course/images/kernel_addr_space.png differ diff --git a/course/images/linux_kernel_boot.png b/course/images/linux_kernel_boot.png new file mode 100644 index 0000000000000000000000000000000000000000..049456a0193cd0b68dabe51c49aa1d51e671931d Binary files /dev/null and b/course/images/linux_kernel_boot.png differ diff --git a/course/images/memory_fetching.png b/course/images/memory_fetching.png new file mode 100644 index 0000000000000000000000000000000000000000..ab096fcec1aa2095223bba45c86a058976c2df0a Binary files /dev/null and b/course/images/memory_fetching.png differ diff --git a/course/images/mmio_vs_pmio.png b/course/images/mmio_vs_pmio.png new file mode 100644 index 0000000000000000000000000000000000000000..3baf19543dfc1129599d45561c21646795d5d8f8 Binary files /dev/null and b/course/images/mmio_vs_pmio.png differ diff --git a/course/images/mmu.png b/course/images/mmu.png new file mode 100644 index 0000000000000000000000000000000000000000..a829c6053f66c2dfb30922bf9eb6fc4e96a0a1ed Binary files /dev/null and b/course/images/mmu.png differ diff --git a/course/images/monkey_cga.png b/course/images/monkey_cga.png new file mode 100644 index 0000000000000000000000000000000000000000..aa064e45fa2399a052028aed50fcdd0579b35947 Binary files /dev/null and b/course/images/monkey_cga.png differ diff --git a/course/images/monkey_ega.png b/course/images/monkey_ega.png new file mode 100644 index 0000000000000000000000000000000000000000..e27421056ae7c9f9c99a93dde2379eebb7b8acc2 Binary files /dev/null and b/course/images/monkey_ega.png differ diff --git a/course/images/monkey_vga.png b/course/images/monkey_vga.png new file mode 100644 index 0000000000000000000000000000000000000000..7951f35e35476f13101237fc1c1f87a1398bb174 Binary files /dev/null and b/course/images/monkey_vga.png differ diff --git a/course/images/multi_level_paging.png b/course/images/multi_level_paging.png new file mode 100644 index 0000000000000000000000000000000000000000..6153cc10e7b0aab741af6b797000fbfd1629ea4a Binary files /dev/null and b/course/images/multi_level_paging.png differ diff --git a/course/images/multiple_processes.png b/course/images/multiple_processes.png new file mode 100644 index 0000000000000000000000000000000000000000..55c3abc4858207a9c89963e57b43a640897a930d Binary files /dev/null and b/course/images/multiple_processes.png differ diff --git a/course/images/multiple_processes_address_spaces.png b/course/images/multiple_processes_address_spaces.png new file mode 100644 index 0000000000000000000000000000000000000000..16cebbef396c98cd88a0f8cd8165dedd5df547ee Binary files /dev/null and b/course/images/multiple_processes_address_spaces.png differ diff --git a/course/images/paging_2level_page_table.png b/course/images/paging_2level_page_table.png new file mode 100644 index 0000000000000000000000000000000000000000..d3ef42b9b4755849a6bc1bfaeba5982f8c645b48 Binary files /dev/null and b/course/images/paging_2level_page_table.png differ diff --git a/course/images/paging_2level_page_table_compact.png b/course/images/paging_2level_page_table_compact.png new file mode 100644 index 0000000000000000000000000000000000000000..b99e111b6017451d24d06b3958146bef29236847 Binary files /dev/null and b/course/images/paging_2level_page_table_compact.png differ diff --git a/course/images/paging_IA-32.png b/course/images/paging_IA-32.png new file mode 100644 index 0000000000000000000000000000000000000000..60b6794e13ca3b06c9c81b80ade8651dbce338b0 Binary files /dev/null and b/course/images/paging_IA-32.png differ diff --git a/course/images/paging_PTE.png b/course/images/paging_PTE.png new file mode 100644 index 0000000000000000000000000000000000000000..d9cf2ac0e47df73f691a3871ca4e283105430674 Binary files /dev/null and b/course/images/paging_PTE.png differ diff --git a/course/images/paging_linear_page_table.png b/course/images/paging_linear_page_table.png new file mode 100644 index 0000000000000000000000000000000000000000..a258e301c3d2fafb21b7804b4395b97bfae57305 Binary files /dev/null and b/course/images/paging_linear_page_table.png differ diff --git a/course/images/paging_shared_pages.png b/course/images/paging_shared_pages.png new file mode 100644 index 0000000000000000000000000000000000000000..d0e4795f9d9c25a8e641ec3d006e8435491d296f Binary files /dev/null and b/course/images/paging_shared_pages.png differ diff --git a/course/images/paging_simple_ex.png b/course/images/paging_simple_ex.png new file mode 100644 index 0000000000000000000000000000000000000000..6876539ec4125fba3215cd645112d44ffc0d076c Binary files /dev/null and b/course/images/paging_simple_ex.png differ diff --git a/course/images/paging_virtual_address_ex_1.png b/course/images/paging_virtual_address_ex_1.png new file mode 100644 index 0000000000000000000000000000000000000000..aba0e694c1f69f24f0907c0c3b78bcdfc825a648 Binary files /dev/null and b/course/images/paging_virtual_address_ex_1.png differ diff --git a/course/images/paging_virtual_address_ex_2.png b/course/images/paging_virtual_address_ex_2.png new file mode 100644 index 0000000000000000000000000000000000000000..ba8a9d108dd99380468a09ee69287621d124c911 Binary files /dev/null and b/course/images/paging_virtual_address_ex_2.png differ diff --git a/course/images/paging_virtual_address_ex_3.png b/course/images/paging_virtual_address_ex_3.png new file mode 100644 index 0000000000000000000000000000000000000000..fbe7923fd72570b3a1626bc091896599c974f1cf Binary files /dev/null and b/course/images/paging_virtual_address_ex_3.png differ diff --git a/course/images/paging_virtual_address_ex_4.png b/course/images/paging_virtual_address_ex_4.png new file mode 100644 index 0000000000000000000000000000000000000000..6bd40b49a16386d253a14d0507f55b50c8acbbaf Binary files /dev/null and b/course/images/paging_virtual_address_ex_4.png differ diff --git a/course/images/part_table_gpt.png b/course/images/part_table_gpt.png new file mode 100644 index 0000000000000000000000000000000000000000..01eb68328333eface4167f859de640e343296005 Binary files /dev/null and b/course/images/part_table_gpt.png differ diff --git a/course/images/part_table_mbr.png b/course/images/part_table_mbr.png new file mode 100644 index 0000000000000000000000000000000000000000..fa47863cf521584b59388e29ffce900012968d12 Binary files /dev/null and b/course/images/part_table_mbr.png differ diff --git a/course/images/pic.png b/course/images/pic.png new file mode 100644 index 0000000000000000000000000000000000000000..6a00b2c9d4309d985c74f756036d566101401dfe Binary files /dev/null and b/course/images/pic.png differ diff --git a/course/images/pic_cascade.png b/course/images/pic_cascade.png new file mode 100644 index 0000000000000000000000000000000000000000..63b2f7af20a100bcf840008ea6617b65b895c34e Binary files /dev/null and b/course/images/pic_cascade.png differ diff --git a/course/images/process_address_space.png b/course/images/process_address_space.png new file mode 100644 index 0000000000000000000000000000000000000000..5d99828fbcd797682a4f2d7ddf330bfbf8bae87c Binary files /dev/null and b/course/images/process_address_space.png differ diff --git a/course/images/process_address_space_fetching.png b/course/images/process_address_space_fetching.png new file mode 100644 index 0000000000000000000000000000000000000000..e58eddfa14e719469f0e05803a7258860939745c Binary files /dev/null and b/course/images/process_address_space_fetching.png differ diff --git a/course/images/process_relocation.png b/course/images/process_relocation.png new file mode 100644 index 0000000000000000000000000000000000000000..73ed38e5834a09cf10ed1200887542fe3e8f510f Binary files /dev/null and b/course/images/process_relocation.png differ diff --git a/course/images/processes_and_phys_address_space.png b/course/images/processes_and_phys_address_space.png new file mode 100644 index 0000000000000000000000000000000000000000..77e594fe2eae43d1e6500894adba2ff0cc289189 Binary files /dev/null and b/course/images/processes_and_phys_address_space.png differ diff --git a/course/images/protection_rings.png b/course/images/protection_rings.png new file mode 100644 index 0000000000000000000000000000000000000000..edd8bbd8659c3195704ee3c66c8bc930e1d10703 Binary files /dev/null and b/course/images/protection_rings.png differ diff --git a/course/images/segmentation.png b/course/images/segmentation.png new file mode 100644 index 0000000000000000000000000000000000000000..03009ed032e0c1959745ca0b5a24903ccffa831a Binary files /dev/null and b/course/images/segmentation.png differ diff --git a/course/images/syscall_full_workflow.png b/course/images/syscall_full_workflow.png new file mode 100644 index 0000000000000000000000000000000000000000..4ce6f70fe251b769d25a480166fe9db303f2e808 Binary files /dev/null and b/course/images/syscall_full_workflow.png differ diff --git a/course/images/syscalls.png b/course/images/syscalls.png new file mode 100644 index 0000000000000000000000000000000000000000..0cf71e3b0b733414f7c744d24a837c393c7676ba Binary files /dev/null and b/course/images/syscalls.png differ diff --git a/course/images/syscalls_dispatch_table.png b/course/images/syscalls_dispatch_table.png new file mode 100644 index 0000000000000000000000000000000000000000..a16652636a3370741ab10c4fe5556078e0f43597 Binary files /dev/null and b/course/images/syscalls_dispatch_table.png differ diff --git a/course/images/syscalls_julia_evans.png b/course/images/syscalls_julia_evans.png new file mode 100644 index 0000000000000000000000000000000000000000..801732396c31c29fd21daea5427c46af7ccd83c1 Binary files /dev/null and b/course/images/syscalls_julia_evans.png differ diff --git a/course/images/task_create1.png b/course/images/task_create1.png new file mode 100644 index 0000000000000000000000000000000000000000..02b4ca7fb2ee9f678af368b5935a26b4014f872e Binary files /dev/null and b/course/images/task_create1.png differ diff --git a/course/images/task_create2.png b/course/images/task_create2.png new file mode 100644 index 0000000000000000000000000000000000000000..c9225d3b81283679941405306a63c4e3fd2b044c Binary files /dev/null and b/course/images/task_create2.png differ diff --git a/course/images/task_create3.png b/course/images/task_create3.png new file mode 100644 index 0000000000000000000000000000000000000000..624f1c80b0975e24ad2097c694f4cdc5f3ba971a Binary files /dev/null and b/course/images/task_create3.png differ diff --git a/course/images/task_create4.png b/course/images/task_create4.png new file mode 100644 index 0000000000000000000000000000000000000000..6c41f893bbde128145923c5f40020d748f36204b Binary files /dev/null and b/course/images/task_create4.png differ diff --git a/course/images/task_create5.png b/course/images/task_create5.png new file mode 100644 index 0000000000000000000000000000000000000000..e03097fd6893717203b85d190c1fe5470c8d9ba4 Binary files /dev/null and b/course/images/task_create5.png differ diff --git a/course/images/task_create6.png b/course/images/task_create6.png new file mode 100644 index 0000000000000000000000000000000000000000..eff18c899d5dbf670e286faf52586df02670746f Binary files /dev/null and b/course/images/task_create6.png differ diff --git a/course/images/task_create7.png b/course/images/task_create7.png new file mode 100644 index 0000000000000000000000000000000000000000..e894ec5adfba849a7c3c9d15edff72aac87f573f Binary files /dev/null and b/course/images/task_create7.png differ diff --git a/course/images/tasks_and_kernel_addr_spaces.png b/course/images/tasks_and_kernel_addr_spaces.png new file mode 100644 index 0000000000000000000000000000000000000000..0603a3681c66667834a5159c2b15de51fa46f032 Binary files /dev/null and b/course/images/tasks_and_kernel_addr_spaces.png differ diff --git a/course/images/tasks_and_kernel_addr_spaces_1.png b/course/images/tasks_and_kernel_addr_spaces_1.png new file mode 100644 index 0000000000000000000000000000000000000000..86b385beb41d1724c5f66be0339d864aa6ad24c9 Binary files /dev/null and b/course/images/tasks_and_kernel_addr_spaces_1.png differ diff --git a/course/images/tasks_and_kernel_addr_spaces_2.png b/course/images/tasks_and_kernel_addr_spaces_2.png new file mode 100644 index 0000000000000000000000000000000000000000..1722bd4a60881bb9b7475db36341de9ccca75cbb Binary files /dev/null and b/course/images/tasks_and_kernel_addr_spaces_2.png differ diff --git a/course/images/tasks_overview.png b/course/images/tasks_overview.png new file mode 100644 index 0000000000000000000000000000000000000000..c753b33b97aceb798672433462537915bcee6353 Binary files /dev/null and b/course/images/tasks_overview.png differ diff --git a/course/images/tss.png b/course/images/tss.png new file mode 100644 index 0000000000000000000000000000000000000000..8dafaff378fba06693afc8fa7eff362324473177 Binary files /dev/null and b/course/images/tss.png differ diff --git a/course/images/tss_crop.png b/course/images/tss_crop.png new file mode 100644 index 0000000000000000000000000000000000000000..54b5e2f38a80698bd3004d7ee2a19bdd3553ad78 Binary files /dev/null and b/course/images/tss_crop.png differ diff --git a/course/images/x86_bootloader.png b/course/images/x86_bootloader.png new file mode 100644 index 0000000000000000000000000000000000000000..20246f81e47f9a44eba5077da6a3fc3fe299ce9b Binary files /dev/null and b/course/images/x86_bootloader.png differ diff --git a/labs/lab1-kernel_display/Makefile b/labs/lab1-kernel_display/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..3c124efda95948aa584656a983f908d2c27a23f6 --- /dev/null +++ b/labs/lab1-kernel_display/Makefile @@ -0,0 +1 @@ +include ../lab.mk diff --git a/labs/lab1-kernel_display/lab1-kernel_display.md b/labs/lab1-kernel_display/lab1-kernel_display.md new file mode 100644 index 0000000000000000000000000000000000000000..08c437eebdb74ef67931a5625c53083a760318ae --- /dev/null +++ b/labs/lab1-kernel_display/lab1-kernel_display.md @@ -0,0 +1,351 @@ +--- +title : Programmation Système Avancée +solutions : false +author : + - "Professeur : Florent Gluck" +date : \today +papersize : A4 +geometry : "left=2.5cm,right=2cm,top=1.5cm,bottom=2cm" +colorlinks : urlcolor +fontsize : 11pt +lang : fr-CH +--- + +# Lab1 - Mini noyau avec affichage graphique + +## Introduction + +Ce travail pratique couvre les premières briques de base dans la réalisation d'un système d’exploitation (OS), à savoir un mini noyau capable de : + +- gérer l'affichage de pixels et de texte ; +- gérer les modules de boot ; +- récupérer et afficher les informations de base du système. + +## Objectifs + +Les objectifs à réaliser dans le cadre de ce travail pratique sont décrits dans les sous-sections qui suivent. Afin de vous laisser une certaine liberté, seules les fonctionnalités requises sont décrites. Vous êtes donc libres sur les détails des fonctions à implémenter. + +La Figure 1 illustre un exemple d'affichage répondant au cahier des charges. + +{ width=86% } + +### Objectif 1 : affichage graphique VBE 640x480 en 16bpp + +On désire pouvoir afficher des pixels, mais aussi du texte. Dans ces deux cas, les coordonnées sont différentes. + +Au niveau de l'affichage de pixels, les coordonnées (0,0) représentent le pixel dans le coin supérieur gauche de l'écran. La première coordonnée est la coordonnée x (ou colonne) et la deuxième coordonnée est la coordonnée y (ou ligne). Aux coordonnées (1,0) se trouve le pixel à la colonne suivante, etc. + +Au niveau de l'affichage de texte, les coordonnées (0,0) représentent le caractère dans le coin supérieur gauche de l'écran. La première coordonnée est la coordonnée x (ou colonne) et la deuxième coordonnée est la coordonnée y (ou ligne). Aux coordonnées (1,0) se trouve le caractère à la colonne suivante, etc. Etant donné que la police qui vous est fournie est de taille 8 x 16 pixels, chaque colonne fait 8 pixels de large et chaque ligne 16 pixels de haut. Les caractères ont tous la même taille, à savoir 8 pixels de largeur sur 16 pixels de haut. De plus, l'affichage de texte est réalisé à la position courante du curseur (celui-ci est "virtuel", car il n'est pas visible). Initialement, le curseur se trouve à la position (0,0). A chaque affichage de texte, le curseur est automatiquement mis à jour de sorte que le prochain affichage de texte soit réalisé à la nouvelle position du curseur. C'est exactement le même comportement qu'on observe dans un shell par exemple. Pour simplifier, vous n'avez pas à afficher le curseur. + +Voici les fonctionnalités d'affichage à réaliser\ : + +- Code du boostrap demandant à GRUB d'initialiser le mode graphique 640x480 en 16bpp +- Fonction "initialisant" le mode graphique ; typiquement cette fonction efface l'écran et initialise les structures internes liées à l'affichage. +- Fonction affichant un pixel aux coordonnées 2D (x,y) avec la couleur spécifiée. +- Fonction effaçant le framebuffer avec la couleur spécifiée. +- Fonction similaire à `printf` affichant un texte formaté à arguments variables à la position 2D courante du curseur ; les formats minimum à gérer sont\ : `%c`, `%s`, `%d` et `%x` ; + - le texte est affiché avec les couleurs de texte et de fond courantes ; + - le caractère "retour chariot" `\n` doit être géré et produire un retour en début de ligne suivante ; + - lorsque le texte à afficher arrive à la fin de la dernière ligne, alors le texte doit défiler verticalement d'une ligne, comme ce qui est réalisé dans un shell ; ce défilement doit également se produire si on se trouve sur la dernière ligne et on presse la touche *enter*. +- Fonction(s) pour changer la couleur courante du texte et du fond. +- Fonction pour changer la position 2D (x,y) du curseur. + +### Objectif 2 : gestion des modules de boot + +Un module de boot est simplement la possibilité par GRUB de charger automatique un fichier en RAM. On peut ensuite utiliser ce contenu dans notre noyau. Ceci peut être utilisé dans beaucoup de scénarios, par exemple pour charger des images graphiques, une image d'un système de fichiers, des programmes à être exécutés, etc. + +Toutefois, il est nécessaire de développer une petite API afin de faciliter l'utilisation de modules de boot au sein du noyau. + +Voici les fonctionnalités à implémenter dans le cadre du support des modules de boot\ : + +- Fonction permettant d'obtenir le nombre de modules de boot détectés. +- Fonction permettant d'obtenir l'adresse d'un module (p.ex. selon son indice). +- Fonction permettant d'obtenir la taille d'un module. +- Fonction permettant d'obtenir la ligne de commande d'un module. +- Fonction permettant d'obtenir la dernière adresse mémoire utilisée par tous les modules (l'adresse du dernier octet faisant partie du dernier module) ; + - cette fonction sera particulièrement utile lors du travail pratique suivant. + +### Objectif 3 : comportement du noyau + +Le noyau doit réaliser les opérations suivantes (pas forcément dans l'ordre listé ici)\ : + +- Initialiser le mode graphique. +- Afficher la quantité de mémoire physique (RAM) disponible (voir `multiboot.h/.c` pour obtenir la quantité de RAM disponible). +- Afficher les caractéristiques du mode vidéo utilisé\ : résolution, bits par pixel, pitch, adresse virtuelle du framebuffer. +- Afficher l'adresse physique à laquelle le noyau est chargé et sa taille en KB. +- Afficher le nombre de modules de boot chargés, et pour chacun\ : adresse de départ, taille, et ligne de commande +- Afficher le message de bienvenue de votre choix : + - le message doit se trouver dans un fichier placé dans le répertoire `resources` + - ce fichier doit être intégrée à l'image ISO sous forme d'un module de boot +- Afficher un logo graphique (image bitmap) de votre choix : + - l'image bitmap doit être intégrée à l'image ISO sous forme d'un module de boot + - la résolution de l'image doit être spécifiée sur la ligne de commande du module de boot et "parsée" par votre noyau + - ainsi, on doit pouvoir changer l'image sans que le code du noyau n'ait à être modifié + - pour faire simple, utilisez le logiciel `gimp` pour créer votre image (ou utilisez une image existante) + - exportez l'image ("Export As...") dans le format "Raw image data", type "Standard (R,G,B)", "R,G,B (normal)" +- Tester que votre code se comporte correctement\ ; on doit pouvoir visuellement confirmer que\ : + - les informations système affichées sont correctes (RAM, infos sur le mode graphique, etc.) + - l'affichage des pixels est correct + - la fonction d'affichage de texte est complète et correcte + - le défilement vertical est correct + - la gestion des couleurs est correcte + - le message de bienvenue et le logo sont affichés correctement +- Votre noyau doit simplement se terminer avec la fonction `halt()` disponible dans `x86.h` + +### Conventions pour l'écriture du code C + +Il est important de prendre des bonnes habitudes lors de l'écriture du code. Ceci sera particulièrement vrai en entreprise où vous collaborerez avec d'autres développeu-ses-rs. Essayez donc de respecter les conventions suivantes pour votre code C : + +- Aucune déclaration de variable ne doit se trouver dans un fichier header (`.h`) +- Toute fonction doit être déclarée `static`, sauf si elle est "publique", c'est-à-dire utilisée dans d'autres modules +- Toute fonction "publique" doit être déclarée dans le header (interface) du module (`.h`) +- Evitez d'utiliser des variables globales lorsque c'est possible +- Toute variable globale doit être déclarée `static`, sauf si elle est "publique", c'est-à-dire utilisée dans d'autres modules +- Toute variable "publique" doit être déclarée `extern` dans le header (interface) du module (`.h`) +- Evitez des noms de variables à rallonge +- Choisissez une langue et tenez-y vous : français ou anglais, mais pas de franglais +- Choisissez un style de code et tenez-y vous : `we_love_c` ou `WeLoveC`, mais pas `WeLove_c` +- Evitez de commenter des portions de code triviaux +- Le code doit être suffisamment clair pour être auto-compréhensible ; si ce n'est pas le cas, alors ajoutez des commentaires d'explications +- Toute partie de code obscure doit être commentée afin qu'une personne tierce puisse en comprendre la teneur + +## Structure du projet fourni + +Pour éviter de tout écrire depuis zéro, un squelette de noyau et fonctions de base vous est fourni sur le git dans le répertoire `lab1`. + +Le code source du projet est structuré en plusieurs répertoires et sous-répertoires afin de modulariser le code et d'en faciliter sa compréhension : + +\footnotesize +``` +|-- common +| |-- colors.h +| |-- Makefile +| |-- mem.c +| |-- mem.h +| |-- stdio.c +| |-- stdio.h +| |-- string.c +| |-- string.h +| `-- types.h +|-- grub +| `-- grub.cfg +|-- kernel +| |-- boot +| | |-- bootstrap_asm.s +| | |-- multiboot.c +| | |-- multiboot.h +| | `-- multiboot_structs.h +| |-- drivers +| | |-- font.c +| | `-- font.h +| |-- mem +| | |-- gdt_asm.s +| | |-- gdt.c +| | `-- gdt.h +| |-- task +| | `-- tss.h +| |-- Makefile +| |-- const.inc +| |-- descriptors.h +| |-- kernel.c +| |-- kernel.ld +| `-- x86.h +|-- common.mk +`-- Makefile +``` +\normalsize + +Le code ci-dessus contient déjà un certain nombre de parties de base et essentielles afin que vous ne commenciez pas complètement de rien. La section suivante décrit chacune de ces parties fournies. + +## Description du code fourni + +### Système de *build* + +Le système de *build* est basé sur une hiérarchie de makefiles permettant de\ : + +- compiler le code partagé (`common`) +- compiler le noyau (`kernel`) +- générer une image ISO du système d'exploitation +- exécuter le système d'exploitation dans QEMU +- débogger le système d'exploitation dans QEMU +- déployer le système d'exploitation sur une clé USB (que vous pouvez ensuite booter sur un vrai PC) +- supprimer tous les fichiers générés + +Le fichier `Makefile` qui se trouve à la racine du projet s'occupe d’appeler les makefiles enfants se trouvant dans les sous-répertoires de chaque sous-parties du projet. Afin de modulariser le contenu des makefiles, les parties de code communes sont modularisées dans le fichier `common.mk` situé à la racine. Celui-ci est inclus par les différents makefiles du projet. + +A la racine du projet, tapez `make` pour obtenir la liste des cibles disponibles\ : + +\scriptsize +``` +Available targets: +run build the OS ISO image (+ filsystem) and run it in QEMU +iso build the OS ISO image (+ filesystem) +common build the common object files only +kernel build the kernel only +debug build the OS ISO image (+ filsystem) and run it in QEMU for debugging +deploy build the OS ISO image (+ filsystem) and deploy it to the specified device + Requires DEV to be defined (eg. DEV=/dev/sdb) +clean clean up everything + +Available variables: +SYSTEM target system type, either UEFI or BIOS (default: UEFI) +PLATFORM target platform type, either QEMU or PC (default: QEMU) +DEBUG whether to generate debug code, either on or off (default: on) +DEV device to deploy the ISO image onto (only used by the "deploy" target) + +Usage examples: +make run +make run SYSTEM=BIOS PLATFORM=QEMU +make PLATFORM=PC DEBUG=0 DEV=/dev/sda deploy +``` +\normalsize + +### Configuration GRUB + +La configuration de GRUB se trouve dans `grub/grub.cfg`. + +Vous devrez la modifier afin d'y ajouter vos modules. + +### Code partagé + +Le code partagé se trouve dans `common`\ : + +\footnotesize +``` +common +|-- colors.h +|-- Makefile +|-- mem.c +|-- mem.h +|-- stdio.c +|-- stdio.h +|-- string.c +|-- string.h +`-- types.h +``` +\normalsize + +Le but de ce répertoire est de fournir des fonctionnalités communes au noyau (répertoire `kernel`), aux applications utilisateur (répertoire `user`) et aux outils (répertoire `tools`). Par exemple, il est fort probable que des fonctions comme `memset` ou `strncmp` soit utilisées dans le noyau et dans les applications utilisateurs. Autant donc les implémenter une seule fois et réutiliser le même code. + +Les fichiers `mem.h` et `mem.c` implémentent quelques fonctions permettant de remplir ou copier des zones mémoires à l'image des fonctions `memset` et `memcpy` de la librairie standard C. + +Les fichiers `stdio.h` et `stdio.c` contiennent les fonctions à arguments variables, `vsnprintf` et `snprintf`, qui écrivent un string formatté dans un buffer. La différence entre ces deux fonctions est que `snprintf` prends un nombre d'arguments variables alors que `vsnprintf` prend un argument de type `va_list`. + +Les fichiers `string.h` et `string.c` implémentent des fonctions classiques de manipulation de string comme `strlen`, `strncpy`, `atoi`, etc. + +Le fichier `colors.h` fourni des couleurs prédéfinies et la macro `RGB(r,g,b)` permet de convertir une couleur RGB888 (24 bits) en une couleur au format demandé sur 16 bits, de type RGB565\ : 5 bits pour la composante rouge (bits 15-11), 6 bits pour la composante verte (bits 10-5), 5 bits pour la composante bleue (bits 4-0). A titre informatif, la notation R5:G6:B5 est souvent utilisée[^2]. Le corps de la macro `RGB` est vide, donc il vous faudra l'implémenter. + +[^2]: D'autres exemples de formats : R8:G8:B8:A8, R5:G5:B5, B5:G6:R5, etc. + +### Code boostrap et multiboot + +Ce code se trouve dans `kernel/boot`\ : + +\footnotesize +``` +kernel +`-- boot + |-- bootstrap_asm.s + |-- multiboot.c + |-- multiboot.h + `-- multiboot_structs.h +``` +\normalsize + +Le fichier `bootstrap_asm.s` implémente le code de bootstrap multiboot nécessaire : + +- à l'initialisation du mode graphique VBE +- à l'initialisation de la pile noyau +- à l'appel du point d'entrée du kernel : la fonction `kernel_main` se trouvant dans `kernel.c`. + +GRUB place dans le registre `EBX`, l'adresse de la structure `multiboot_info_t` se trouvant dans le fichier `multiboot_structs.h`. Un pointeur sur cette structure est récupéré dans la fonction `kernel_main` pour être sauvegardé dans une variable globale, fonctionnalité réalisée par la ligne\ : + +\footnotesize +```{.c} +multiboot_set_info(mbi); +``` +\normalsize + +Ainsi, cette structure `multiboot_info_t` pourra le cas échéant être récupérée depuis n'importe où dans le code. + +Les fichiers `multiboot.h` et `multiboot.c` implémentent une API permettant de manipuler la structure `multiboot_info_t`\ : + +Fonction Description +----------------------------------------------------------- -------------------------------------------------------- +\scriptsize `void multiboot_set_info(multiboot_info_t *)` Sauvegarde, dans une variable interne, + un pointeur sur la structure `multiboot_info_t` +\scriptsize `multiboot_info_t* multiboot_get_info()` Retourne un pointeur sur la structure + `multiboot_info_t` sauvegardée auparavant +\scriptsize `uint_t multiboot_get_RAM_in_KB()` Retourne la quantité de mémoire physique disponible + en KB +-------------------------------------------------------------------------------------------------------------------- + +### Code lié à l'affichage + +Comme mentionné auparavant, l'affichage graphique désiré est un mode VBE d'une résolution de 640x480 pixels où chaque pixel est encodé sur 16 bits. Cela signifie que $2^{16}$ = 65536 couleurs sont affichables simultanément à l'écran. La configuration mémoire de chaque pixel est décrite plus haut dans la sous-section "Code partagé". + +A vous de modifier le fichier `bootstrap_asm.s` afin de demander à GRUB d'initialiser le mode graphique souhaité. Si le mode est supporté par le matériel (c'est le cas avec QEMU pour le mode 640x480 16bpp), GRUB s'occupe alors de remplir plusieurs champs dans la structure `multiboot_info_t` avec les détails du mode graphique initialisé, à savoir\ : `framebuffer_addr`, `framebuffer_width`, `framebuffer_height`, `framebuffer_bpp` et `framebuffer_pitch`. + +Il est important que votre code se base sur ces champs et que rien lié à l'affichage ne soit codé en dur. Par exemple, si on décidait de changer la résolution graphique dans le boostrap à 800x600, alors l'affichage de votre OS devrait s'adapter automatiquement, sans que le code de celui-ci n'ait à être modifié\ ! + +**Rappel théorique** : il n'y a **aucune garantie** que le *pitch* du framebuffer corresponde à la largeur du framebuffer, donc tenez-en compte dans votre code d'affichage. + +Afin de vous aider avec l'affichage de texte, les fichiers `font.c` et `font.h` fournis vous mettent à disposition une police de caractères de taille 8x16 où chaque ligne du tableau `font_8x16` représente un caractère et chaque pixel est représenté sur 1 bit. + +### Code lié à la gestion mémoire + +Le code lié à la gestion mémoire se trouve dans `kernel/mem`. Vous pouvez l'ignorer pour le moment. + +### Autres fichiers du noyau + +Les sections précédentes ont présentés les parties les plus importantes du noyau. Ici, je présente les fichiers qui n'ont pas encore été décrits et qui font également partie du noyau\ : + +\footnotesize +``` +kernel +|-- task +| `-- tss.h +|-- Makefile +|-- const.inc +|-- descriptors.h +|-- kernel.c +|-- kernel.ld +`-- x86.h +``` +\normalsize + +Fichier Description +--------------- ----------------------------------------------------------------------- +`const.inc` constantes utilisées dans le code assembleur pour la GDT +`descriptors.h` définitions des descripteurs utilisés dans le code lié à la GDT et dans le + code ultérieur lié aux interruptions et aux tâches +`kernel.c` point d'entrée du noyau +`kernel.ld` fichier décrivant où reloger les différentes sections du noyau lors de + l'édition des liens du fichier `kernel.elf` +`tss.h` structure matérielle d'une tâche pour l'architecture IA-32 ; sera utilisé dans + le code ultérieur de gestion de tâches +`x86.h` contient 3 fonctions spécifiques à l'architecture x86 : + `cli()` : masque les interruptions matérielles + `sti()` : démasque les interruptions matérielles + `halt()` : stoppe l'exécution du processeur +--------------------------------------------------------------------------------------- + +## Remarques importantes + +- Pensez à placer vos fichiers sources à un endroit dans la hiérarchie de fichiers **qui fait du sens**. Vous êtes libres de modifier la structure existante du projet et de rajouter/modifier/supprimer des répertoires. + +- Rappelez-vous que vous **n'avez pas de librairie C** disponible, donc pas de fonctions `malloc`, `printf`, etc. ! Pas de `malloc` (et dérivés) signifie pas d'allocation dynamique possible. + +<!-- +- Assurez-vous que votre code respecte les consignes décrites dans les documents se trouvant dans la section "Consignes écriture code" sur Cyberlearn. +--> + +## Conseils + +Commencez par étudiez le code existant afin vous imprégner de la structure du projet. Mieux vous comprendrez le code et la structure du projet, plus vous serez efficaces. Vous retrouverez également ce code lors des examens de programmation live. Il est donc important que vous soyez à l'aise avec le code fourni. + +Enfin, appropriez-vous le code : vous pouvez le changer comme bon vous semble (modifications, ajouts, etc.). Le but est que celui-ci devienne votre\ ! + +## Echéance + +Ce travail pratique est à terminer pour le 3 octobre.