Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
226 changes: 135 additions & 91 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,91 +1,135 @@
# -----------Product Config-----------
# product name
PRODUCT_NAME = TOY_OS
BUILD_DIR = build
# -----------Disk Image Config-----------
# image file name
DISK_IMAGE = $(BUILD_DIR)/disk.img
# disk size in MB, can be specified by command line
DISK_SIZE ?= 64
# sector size, 512 bytes by default
SECTOR_SIZE = 512
# partition offset in sector, 2048 by default because of 4KB alignment
PART_START = 2048
# end partition, partition size - 1 is the last partition
PART_END = $(shell echo $$((($(DISK_SIZE) * 1024 * 1024) / $(SECTOR_SIZE) - 1)))
# partition type, `0c` for FAT32
TYPE = 0c
# mount point
MOUNT_POINT ?= /mnt/toy_os
# -----------C Compiler Config-----------
CFLAGS = -Wall -static -fno-stack-protector -m32 -I.

.PHONY: clean mount unmount build run

# -----------make-----------
run: build
qemu-system-x86_64 -drive file=$(DISK_IMAGE),format=raw

build: $(BUILD_DIR)/flag_installed

$(BUILD_DIR):
mkdir -p $@

# make disk image
$(DISK_IMAGE):
# create an empty disk image file filled with zeros
dd if=/dev/zero of=$@ bs=1M count=$(DISK_SIZE)
# create a MBR partition table with a FAT32 partition
echo "o\nn\np\n1\n$(PART_START)\n$(PART_END)\nt\n$(TYPE)\nw\n" | fdisk $@
# format the partition as FAT32
mkfs.vfat -F 32 -n "$(PRODUCT_NAME)" --offset $(PART_START) $@

# -----------MBR Boot Code-----------
BUILD_BOOT_DIR = $(BUILD_DIR)/boot

$(BUILD_BOOT_DIR): $(BUILD_DIR)
mkdir -p $@

$(BUILD_BOOT_DIR)/mbr_boot_asm.o: boot/mbr_boot.asm $(BUILD_BOOT_DIR)
nasm $< -f elf32 -o $(BUILD_BOOT_DIR)/mbr_boot_asm.o

$(BUILD_BOOT_DIR)/mbr_boot_c.o: boot/mbr_boot.c $(BUILD_BOOT_DIR)
gcc $(CFLAGS) -nostdinc -fno-builtin -fno-pie -fno-pic -fno-omit-frame-pointer -fno-strict-aliasing -s -c -o $(BUILD_BOOT_DIR)/mbr_boot_c.o $<

$(BUILD_BOOT_DIR)/mbr_boot.o: $(BUILD_BOOT_DIR)/mbr_boot_asm.o $(BUILD_BOOT_DIR)/mbr_boot_c.o
# param explaination:
# -N: Do not page align data, do not make text readonly
# -e: Set entry point
# -Ttext: Set address of .text section
# -s: Strip all symbols
ld -m elf_i386 -N -e asm_main -Ttext 0x7c00 -s $(BUILD_BOOT_DIR)/mbr_boot_asm.o $(BUILD_BOOT_DIR)/mbr_boot_c.o -o $(BUILD_BOOT_DIR)/mbr_boot.o

$(BUILD_BOOT_DIR)/mbr_boot.bin: $(BUILD_BOOT_DIR)/mbr_boot.o
# param explaination:
# -S: Strip all symbols and relocation information
# -O: Output target
# -j .text: Only copy section .text into the output
objcopy -S -O binary -j .text -j .rodata $(BUILD_BOOT_DIR)/mbr_boot.o $(BUILD_BOOT_DIR)/mbr_boot.bin

$(BUILD_DIR)/flag_installed: $(BUILD_DIR)/boot/mbr_boot.bin $(DISK_IMAGE)
# make sure the size is less than 440 bytes
[ $(shell stat -c %s build/boot/mbr_boot.bin) -lt 440 ]
dd if=$< of=$(DISK_IMAGE) bs=440 count=1 conv=notrunc
touch $(BUILD_DIR)/flag_installed

# -----------clean-----------
clean:
rm -rf $(BUILD_DIR)

# -----------mount disk image-----------
mount:
sudo mkdir -p $(MOUNT_POINT)
LOOPDEV=$$(sudo kpartx -av $(DISK_IMAGE) | head -n 1 | cut -d ' ' -f 3); \
echo "Loop device: $$LOOPDEV"; \
sudo mount /dev/mapper/$$LOOPDEV $(MOUNT_POINT)

# -----------unmount disk image-----------
unmount:
sudo umount $(MOUNT_POINT)
sudo kpartx -dv $(DISK_IMAGE)
sudo rm -rf $(MOUNT_POINT)
-include local.mk

X64 ?= yes

ifeq ("$(X64)","yes")
BITS = 64
XOBJS = kobj/vm64.o
XFLAGS = -m64 -DX64 -mcmodel=kernel -mtls-direct-seg-refs -mno-red-zone
LDFLAGS = -m elf_x86_64
QEMU ?= qemu-system-x86_64
else
XFLAGS = -m32
LDFLAGS = -m elf_i386
QEMU ?= qemu-system-i386
endif

OPT ?= -O0

OBJS := \
kobj/console.o\
kobj/main.o\
kobj/string.o\
kobj/vm.o\
kobj/memblock.o\

ifneq ("$(MEMFS)","")
# build filesystem image in to kernel and use memory-ide-device
# instead of mounting the filesystem on ide1
OBJS := $(filter-out kobj/ide.o,$(OBJS)) kobj/memide.o
endif

# Cross-compiling (e.g., on Mac OS X)
#TOOLPREFIX = i386-jos-elf-

# Using native tools (e.g., on X86 Linux)
#TOOLPREFIX =

CC = $(TOOLPREFIX)gcc
AS = $(TOOLPREFIX)gas
LD = $(TOOLPREFIX)ld
OBJCOPY = $(TOOLPREFIX)objcopy
OBJDUMP = $(TOOLPREFIX)objdump
CFLAGS = -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -MD -ggdb -fno-omit-frame-pointer
CFLAGS += -ffreestanding -fno-common -nostdlib -Iinclude -gdwarf-2 $(XFLAGS) $(OPT)
CFLAGS += $(shell $(CC) -fno-stack-protector -E -x c /dev/null >/dev/null 2>&1 && echo -fno-stack-protector)
ASFLAGS = -fno-pic -gdwarf-2 -Wa,-divide -Iinclude $(XFLAGS)

xv6.img: out/bootblock out/kernel.elf
dd if=/dev/zero of=xv6.img count=10000
dd if=out/bootblock of=xv6.img conv=notrunc
dd if=out/kernel.elf of=xv6.img seek=1 conv=notrunc

xv6memfs.img: out/bootblock out/kernelmemfs.elf
dd if=/dev/zero of=xv6memfs.img count=10000
dd if=out/bootblock of=xv6memfs.img conv=notrunc
dd if=out/kernelmemfs.elf of=xv6memfs.img seek=1 conv=notrunc

# kernel object files
kobj/%.o: kernel/%.c
@mkdir -p kobj
$(CC) $(CFLAGS) -c -o $@ $<

kobj/%.o: kernel/%.S
@mkdir -p kobj
$(CC) $(ASFLAGS) -c -o $@ $<

out/bootblock: kernel/bootasm.S kernel/bootmain.c
@mkdir -p out
$(CC) -fno-builtin -fno-pic -m32 -nostdinc -Iinclude -O -o out/bootmain.o -c kernel/bootmain.c
$(CC) -fno-builtin -fno-pic -m32 -nostdinc -Iinclude -o out/bootasm.o -c kernel/bootasm.S
$(LD) -m elf_i386 -N -e start -Ttext 0x7C00 -o out/bootblock.o out/bootasm.o out/bootmain.o
$(OBJDUMP) -S out/bootblock.o > out/bootblock.asm
$(OBJCOPY) -S -O binary -j .text out/bootblock.o out/bootblock
tools/sign.pl out/bootblock

ENTRYCODE = kobj/entry$(BITS).o
LINKSCRIPT = kernel/kernel$(BITS).ld
out/kernel.elf: $(OBJS) $(ENTRYCODE) $(LINKSCRIPT)
$(LD) $(LDFLAGS) -T $(LINKSCRIPT) -o out/kernel.elf $(ENTRYCODE) $(OBJS) -b binary
$(OBJDUMP) -S out/kernel.elf > out/kernel.asm
$(OBJDUMP) -t out/kernel.elf | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > out/kernel.sym

MKVECTORS = tools/vectors$(BITS).pl
kernel/vectors.S: $(MKVECTORS)
perl $(MKVECTORS) > kernel/vectors.S

# Prevent deletion of intermediate files, e.g. cat.o, after first build, so
# that disk image changes after first build are persistent until clean. More
# details:
# http://www.gnu.org/software/make/manual/html_node/Chained-Rules.html
.PRECIOUS: uobj/%.o

-include */*.d

clean:
rm -rf out fs uobj kobj
rm -f kernel/vectors.S xv6.img xv6memfs.img fs.img .gdbinit

# run in emulators

bochs : fs.img xv6.img
if [ ! -e .bochsrc ]; then ln -s tools/dot-bochsrc .bochsrc; fi
bochs -q

# try to generate a unique GDB port
GDBPORT = $(shell expr `id -u` % 5000 + 25000)
# QEMU's gdb stub command line changed in 0.11
QEMUGDB = $(shell if $(QEMU) -help | grep -q '^-gdb'; \
then echo "-gdb tcp::$(GDBPORT)"; \
else echo "-s -p $(GDBPORT)"; fi)
ifndef CPUS
CPUS := 2
endif
QEMUOPTS = -net none -hda xv6.img -smp $(CPUS) -m 512 $(QEMUEXTRA)

qemu: xv6.img
$(QEMU) -serial mon:stdio $(QEMUOPTS)

qemu-memfs: xv6memfs.img
$(QEMU) xv6memfs.img -smp $(CPUS)

qemu-nox: fs.img xv6.img
$(QEMU) -nographic $(QEMUOPTS)

.gdbinit: tools/gdbinit.tmpl
sed "s/localhost:1234/localhost:$(GDBPORT)/" < $^ > $@

qemu-gdb: fs.img xv6.img .gdbinit
@echo "*** Now run 'gdb'." 1>&2
$(QEMU) -serial mon:stdio $(QEMUOPTS) -S $(QEMUGDB)

qemu-nox-gdb: fs.img xv6.img .gdbinit
@echo "*** Now run 'gdb'." 1>&2
$(QEMU) -nographic $(QEMUOPTS) -S $(QEMUGDB)

2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

# Toy Kernel

## Get started
Expand All @@ -9,3 +10,4 @@

- run `make` to build and run the os in qemu Virtual Machine.
- run `make build` to build the os image only.

51 changes: 0 additions & 51 deletions boot/gdt.inc

This file was deleted.

63 changes: 0 additions & 63 deletions boot/mbr_boot.asm

This file was deleted.

27 changes: 0 additions & 27 deletions boot/mbr_boot.c

This file was deleted.

Loading