Skip to content
Snippets Groups Projects
Commit 88e8b710 authored by Florent Gluck's avatar Florent Gluck
Browse files

Added source markdown files

parent 3033ac27
Branches
No related tags found
No related merge requests found
Showing
with 574 additions and 0 deletions
---
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
![](images/x86_bootloader.png){ 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)
![](images/part_table_mbr.png){ 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
![](images/part_table_gpt.png){ 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
![](images/linux_kernel_boot.png){ 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)
---
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}
![](images/monkey_cga.png){ width=100% }
![](images/monkey_ega.png){ width=100% }
![](images/monkey_vga.png){ 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
![](images/framebuffer.png){ 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)
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)
course/images/GDT.png

153 KiB

course/images/PICs.png

116 KiB

course/images/address_space.png

138 KiB

course/images/address_space_without_legends.png

51 KiB

course/images/address_translation_x86-64.png

308 KiB

course/images/basic_address_space.png

43.8 KiB

course/images/context.png

889 KiB

course/images/cpu_exceptions.png

1.07 MiB

course/images/exception_handlers.png

292 KiB

course/images/external_fragmentation.png

31.9 KiB

course/images/frame_management.png

38.1 KiB

course/images/frame_management_bitarray.png

36.4 KiB

course/images/framebuffer.png

345 KiB

course/images/hw_int.png

118 KiB

course/images/ia32_mapping_example.png

341 KiB

course/images/identity_mapping.png

56.7 KiB

course/images/idt_and_idtr.png

406 KiB

0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment