summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElizabeth Alexander Hunt <me@liz.coffee>2026-09-28 21:08:07 -0700
committerElizabeth Alexander Hunt <me@liz.coffee>2026-09-28 21:08:07 -0700
commitf2899b62b997aafc25666f21ea3a754030a8de71 (patch)
tree9503136c7639d8478ff90977870f99046a4524f8
downloadhelloOS-f2899b62b997aafc25666f21ea3a754030a8de71.tar.gz
helloOS-f2899b62b997aafc25666f21ea3a754030a8de71.zip
Upload from https://github.com/TheHuddle/pr-practice/pull/10/changesHEADmain
-rw-r--r--.gitignore5
-rw-r--r--Makefile30
-rw-r--r--boot.asm29
-rw-r--r--kernel.c36
-rw-r--r--linker.ld43
-rw-r--r--readme.org15
6 files changed, 158 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5acb32e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+iso/*
+*.o
+*.bin
+*.iso
+
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..c06ff32
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,30 @@
+.DEFAULT_GOAL := os.iso
+.PHONY: demo
+
+OBJECTS=entry.o kernel.o
+KERNEL_BUILD_FLAGS=-std=c99 -ffreestanding -O0 -Wall -Wextra
+OS_BUILD_FLAGS=-ffreestanding -O2 -nostdlib -lgcc
+
+entry.o: boot.asm
+ nasm -felf32 boot.asm -o entry.o
+
+kernel.o: kernel.c
+ i386-elf-gcc -c kernel.c -o kernel.o $(KERNEL_BUILD_FLAGS)
+
+os.bin: kernel.o entry.o
+ i386-elf-gcc -T linker.ld -o os.bin $(OS_BUILD_FLAGS) $(OBJECTS)
+
+os.iso: os.bin
+ mkdir -p iso/boot/grub
+ cp os.bin iso/boot/os.bin
+ printf "menuentry 'HelloOS' {\n multiboot /boot/os.bin\n set gfxpayload=text\n}" > iso/boot/grub/grub.cfg
+ grub-mkrescue -o os.iso iso
+
+demo:
+ qemu-system-i386 demo/os.iso
+
+run: os.iso
+ qemu-system-i386 os.iso
+
+clean:
+ rm -rf iso os.iso *.o *.bin
diff --git a/boot.asm b/boot.asm
new file mode 100644
index 0000000..1627135
--- /dev/null
+++ b/boot.asm
@@ -0,0 +1,29 @@
+MBALIGN equ 1 << 0
+MEMINFO equ 1 << 1
+FLAGS equ MBALIGN | MEMINFO
+MAGIC equ 0x1BADB002
+CHECKSUM equ -(MAGIC + FLAGS)
+
+section .multiboot
+align 4
+ dd MAGIC
+ dd FLAGS
+ dd CHECKSUM
+
+section .bss
+align 16
+stack_bottom:
+resb 16384
+stack_top:
+
+section .text
+global _start:function (_start.end - _start)
+_start:
+ mov esp, stack_top
+ extern kernel
+ call kernel
+ cli
+
+jmp $
+
+.end:
diff --git a/kernel.c b/kernel.c
new file mode 100644
index 0000000..190d36e
--- /dev/null
+++ b/kernel.c
@@ -0,0 +1,36 @@
+#include <stddef.h>
+#include <stdint.h>
+
+#define WIDTH 80
+#define HEIGHT 25
+
+#define BLACK 0
+#define BLUE 1
+#define GREEN 2
+#define RED 4
+#define MAGENTA 13
+#define WHITE 15
+
+int strlen(char* s) {
+ int n = 0;
+ char* s_ptr = s;
+ while (*(s_ptr++)) {
+ n++;
+ }
+ return n;
+}
+
+void kernel(void) {
+ uint16_t* vgamem = (uint16_t*) 0xB8000;
+ uint16_t vgacolors[6] = {WHITE | RED << 4, WHITE | GREEN << 4, WHITE | BLUE << 4, BLACK | RED << 4, BLACK | GREEN << 4, BLACK | BLUE << 4};
+ char* s = "Hello world!";
+ int i,j,k;
+ for (k = 0; k >= 0; ++k) {
+ k = (k % 5);
+ j = 0;
+ while (j < 100000000) { j++; } // Since we don't have an interrupt descriptor table we can't use the PIC; this emulates "sleeping"
+ for (i = 0; i < WIDTH*HEIGHT; i++) {
+ vgamem[i] = s[i % strlen(s)] | vgacolors[(i+k) % 6] << 8;
+ }
+ }
+}
diff --git a/linker.ld b/linker.ld
new file mode 100644
index 0000000..38ddd94
--- /dev/null
+++ b/linker.ld
@@ -0,0 +1,43 @@
+/* The bootloader will look at this image and start execution at the symbol
+ designated as the entry point. */
+ENTRY(_start)
+
+/* Tell where the various sections of the object files will be put in the final
+ kernel image. */
+SECTIONS
+{
+ /* Begin putting sections at 1 MiB, a conventional place for kernels to be
+ loaded at by the bootloader. */
+ . = 1M;
+
+ /* First put the multiboot header, as it is required to be put very early
+ early in the image or the bootloader won't recognize the file format.
+ Next we'll put the .text section. */
+ .text BLOCK(4K) : ALIGN(4K)
+ {
+ *(.multiboot)
+ *(.text)
+ }
+
+ /* Read-only data. */
+ .rodata BLOCK(4K) : ALIGN(4K)
+ {
+ *(.rodata)
+ }
+
+ /* Read-write data (initialized) */
+ .data BLOCK(4K) : ALIGN(4K)
+ {
+ *(.data)
+ }
+
+ /* Read-write data (uninitialized) and stack */
+ .bss BLOCK(4K) : ALIGN(4K)
+ {
+ *(COMMON)
+ *(.bss)
+ }
+
+ /* The compiler may produce other sections, by default it will put them in
+ a segment with the same name. Simply add stuff here as needed. */
+}
diff --git a/readme.org b/readme.org
new file mode 100644
index 0000000..161a39f
--- /dev/null
+++ b/readme.org
@@ -0,0 +1,15 @@
+* HelloOS
+This is a simple 32 bit protected mode operating system that runs in VGA mode. It outputs "Hello world" with some cool christmas lights.
+
+#+ATTR_HTML: :style margin-left: auto; margin-right: auto;
+[[https://s10.gifyu.com/images/demo45e010936937dd16.gif]]
+
+** Building
+In order to build this program you must have the ~i386~ GCC cross-compiled on your system. Instructions can be found on the [[https://wiki.osdev.org/GCC_Cross-Compiler][OSDev Wiki]]. You will also need ~grub~ and ~nasm~.
+
+Then, a simple ~make~ will generate the iso. You can run the iso by ~dd~'ing it to a usb stick or by running it with ~qemu-system-i386~. If you are running on native hardware make sure to boot it with BIOS (some PC's call it Legacy Support).
+
+** Using pre-compiled image
+This project contains a pre-compiled iso file in ~demo~. Simply ~cd demo~ and ~qemu-system-i386 os.iso~ or run ~make demo~.
+
+