Files
Exams/AdvOpsys/notes/work-summary-2026-04-10.md
2026-05-31 14:05:22 +02:00

4.8 KiB
Raw Permalink Blame History

Summary of Work Done on April 10, 2026

Overview

Today, work was done on the OSDev_18 project to improve the kernel startup sequence and to make sure the kernel still boots correctly and prints output to the screen. The main focus was to add a minimal Global Descriptor Table (GDT) setup for the i386 version of the kernel and verify that it works as expected.

The project is set up to use a dev container, so the build and test steps were carried out in that environment. This was necessary because the container already includes the required cross-compilation and debugging tools.

GDT Implementation

A minimal GDT was added for 32-bit protected mode. The implementation uses three entries:

  1. A null descriptor
  2. A kernel code segment descriptor
  3. A kernel data segment descriptor

The code and data segments were configured with:

  • base address 0x00000000
  • effective 4 GiB address space
  • 4 KiB granularity
  • ring 0 privilege level

The GDT setup code builds these descriptors in memory and prepares a GDT descriptor that can be loaded by the CPU.

After that, an assembly routine loads the new GDT with lgdt, performs a far jump to reload the code segment register, and then reloads the remaining segment registers for data access. This step is important because loading the GDT alone does not automatically update the segment registers already cached by the processor.

Kernel Startup Changes

The kernel startup code was updated so that the GDT is initialized before the terminal is set up. After the GDT setup is finished, the terminal initialization still runs and the kernel prints Hello, World! to the VGA text buffer.

This means the boot flow now works roughly like this:

  1. The bootloader transfers control to the kernel entry point.
  2. The kernel starts execution in C code.
  3. The GDT is initialized and loaded.
  4. Segment registers are reloaded.
  5. The VGA terminal is initialized.
  6. Hello, World! is printed.
  7. The kernel enters an infinite halt loop.

Build System Changes

The build configuration was updated so the kernel now includes both the new C source for the GDT logic and the new assembly source for the reload routine. This ensures that the GDT implementation is compiled and linked into the kernel binary together with the rest of the startup code.

New build artifacts were generated today, including an updated kernel binary and bootable ISO image.

Documentation Work

The project documentation was also improved today. Short explanations were added to describe:

  • the general kernel boot flow
  • where the GDT setup happens
  • why lgdt is not enough on its own
  • why a far jump and segment-register reload are required after loading the GDT

This was done to make the code easier to follow and to connect the implementation more clearly to the assignment requirements.

Verification and Testing

The GDT implementation was tested in two ways.

1. Static inspection of the kernel binary

The built kernel binary was inspected to confirm that the expected GDT-related symbols were present and that the generated machine code actually contained:

  • a call to load the GDT
  • a far jump to selector 0x08
  • reloads of the data segment registers using selector 0x10

This showed that the expected GDT setup sequence had been compiled into the kernel.

2. Runtime debugging in QEMU with GDB

The kernel was then started in QEMU and examined with gdb-multiarch. During this session, execution was stopped inside the GDT initialization code and inside the assembly reload routine.

The following results were observed:

  • the GDT descriptor size was 0x17, which matches three 8-byte entries minus 1
  • the code segment entry was populated with the expected values
  • after the far jump, the cs register changed to 0x08
  • after stepping through the segment reload instructions, ds, es, fs, gs, and ss all became 0x10

These checks show that the processor did not just compile the code correctly, but also used the new GDT correctly at runtime.

Current State at the End of the Day

At the end of todays work, the OSDev_18 kernel:

  • builds inside the dev container
  • includes a minimal i386 GDT implementation
  • loads the GDT during kernel startup
  • reloads the code and data segment registers correctly
  • still initializes the VGA terminal
  • still prints Hello, World! after boot

Based on the testing that was done today, the GDT implementation appears to be working correctly for this minimal protected-mode kernel setup.

Later Integration Note

Later project stages changed the visible startup order so TerminalInitialize() runs before GdtInitialize() in the final kernel.c. This allows later initialization code to print diagnostics through the terminal. The GDT implementation itself remains part of the early startup path and is still initialized before the interrupt, memory, timing, and application layers are used.