-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMakefile
More file actions
174 lines (139 loc) · 5.52 KB
/
Makefile
File metadata and controls
174 lines (139 loc) · 5.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# Using https://aur.archlinux.org/packages/i386-elf-gcc cross-compiler.
TOOLPREFIX = i386-elf-
CC = $(TOOLPREFIX)gcc
AS = nasm
LD = $(TOOLPREFIX)ld
OBJCOPY = $(TOOLPREFIX)objcopy
OBJDUMP = $(TOOLPREFIX)objdump
# From https://github.com/dreamos82/Osdev-Notes/blob/master/01_Build_Process/02_Overview.md
# `-fno-pie` to avoid: undefined reference to `_GLOBAL_OFFSET_TABLE_'.
# We also need the chain to be consistent: 32-bit
CFLAGS = -std=c17 -fno-pie -nostdlib -ffreestanding
# `-mno-red-zone`: disables the red-zone, a 128 byte region reserved on the
# stack for optimizations. Hardware interrupts are not aware of the red-zone,
# and will clobber it. So we need to disable it in the kernel or we'll lose
# data.
#
# `-fno-omit-frame-pointer`: Sometimes the compiler will skip creating a new
# stack frame for optimization reasons. This will mess with stack traces, and
# only increases the memory usage by a few bytes here and there.
CFLAGS += -mno-red-zone -fno-omit-frame-pointer
CFLAGS += -ggdb
LDFLAGS = -static
ASFLAGS = -g
LDS = kernel.lds
K=kernel
U=user
# Automatically generate lists of sources using wildcards.
C_SRCS = $(wildcard $K/lib/*.c $K/*.c $K/drivers/*.c)
HEADERS = $(wildcard $K/lib/*.h $K/*.h $K/drivers/*.h)
OBJS = $(C_SRCS:.c=.o)
# TODO: Make sources depend on all header files.
HEADER_DEFS = \
$K/idt_defs.h\
$K/paging_defs.h\
$K/syscall_defs.h
# For user programs to link against
ULIB = $U/syscall.o
# Defaul build target
all: os.img
# Run bochs to simulate booting of our code.
run: all
bochs
# Sectors loaded from floppy. As per asm copy_extmem (INT 15h,87h XT-286, AT),
# we shouldn't be able to load more than 40 sectors. Qemu doesn't seem to
# bother but bochs limits to 72 (9000h). Ideally we would allow ourselves the
# max of 0xFFFF bytes ~ 127 * 512.
KERNEL_SECTORS := 72
# This is the actual disk image that the computer loads
# which is the combination of our compiled bootsector and kernel
os.img: boot/stage1.bin boot/stage2.bin kernel.bin $(ULIB)
# Ensure our kernel file doesn't exceed what the bootloader will load from the disk.
bash -c '[ $$(stat -c %s kernel.bin) -lt $$(expr 512 \* $(KERNEL_SECTORS)) ]'
cat $^ /dev/zero | dd of=$@ bs=1k count=1440 iflag=fullblock
fs.img: os.img
dd if=/dev/zero of=fs.img count=10000
dd if=os.img of=fs.img conv=notrunc
# Linking ORDER MATTERS!
OBJS := $K/kernel_entry.o $(OBJS) $K/isr.o $K/gdt_load.o $K/swtch.o
# This builds the binary of our kernel from two object files:
# - the kernel_entry,which jumps to main() in our kernel
# - the compiled C kernel
kernel.bin: $(HEADER_DEFS) $(OBJS) $U/initcode $U/init
# `-b <input-format>` specifies a new binary format for object files
# after this option.
$(LD) $(LDFLAGS) -o kernel.elf -T $(LDS) \
--oformat=elf32-i386 $(OBJS) \
-b binary $U/init \
--print-map > kernel.map
# Note binary (ld or objcopy discards all symbols and relocation information).
$(OBJCOPY) -S -O binary kernel.elf $@
# initcode is superseded by init for now.
$U/initcode: $U/initcode.asm $(ULIB)
$(AS) $(ASFLAGS) $U/initcode.asm -f elf32 -o $U/initcode.o
$(LD) $(LDFLAGS) -N -e start -Ttext 0 -o $U/initcode.out $U/initcode.o $(ULIB)
$(OBJCOPY) -S -O binary $U/initcode.out $U/initcode
$U/init: $U/init.o $(ULIB)
$(LD) $(LDFLAGS) -N -e main -Ttext 0 -o $U/init.out $^
$(OBJCOPY) -S -O binary $U/init.out $U/init
# C init doesn't need gcc stack alignment and stack protection.
# https://reverseengineering.stackexchange.com/questions/15173/what-is-the-purpose-of-these-instructions-before-the-main-preamble
# https://stackoverflow.com/questions/38781118/why-is-gcc-pushing-an-extra-return-address-on-the-stack
# https://stackoverflow.com/questions/45423338/whats-up-with-gcc-weird-stack-manipulation-when-it-wants-extra-stack-alignment
UCFLAGS = -fno-stack-protector
UCFLAGS += -maccumulate-outgoing-args # -mpreferred-stack-boundary=2
$U/init.o: $U/init.c $(HEADERS)
$(CC) -I. -c $< $(CFLAGS) $(UCFLAGS) -o $@
# `-fstack-protector`: requires that we implement __stack_chk_*
KCFLAGS = -fstack-protector
%.o: %.c $(HEADERS)
$(CC) -I. -Ikernel -c $< $(CFLAGS) $(KCFLAGS) -o $@
%.o : %.asm
$(AS) $(ASFLAGS) $< -f elf32 -o $@
%.bin : %.asm
$(AS) $< -f bin -I ./boot -o $@ \
-dKERNEL_SECTORS=$(KERNEL_SECTORS)
%_defs.h: %_defs.asm
sed -e 's/%define/#define/' -e 's/;\+/\/\//' $< > $@
.PHONY: clean
clean:
rm -fr *.bin *.elf *.dis *.o os.img *.map
rm -fr boot/*.bin $K/*.o drivers/*.o $K/*.out
rm -fr $K/*_defs.h
rm -fr $U/initcode $U/init $U/*.o $U/*.out
rm -fr $(OBJS)
.PHONY: run-bochs
run-bochs: all fs.img
bochs -q -f bochsrc
QEMUOPTS = -fda os.img
# As of qemu 6.2, `-smp cpus=2` is `-smp sockets=1,cores=2`, i.e. 1 cpu.
# QEMUOPTS += -smp sockets=2,cores=2
QEMUOPTS += -drive file=fs.img,index=1,media=disk,format=raw
# Exit curses with Alt + 2
.PHONY: run-qemu
run-qemu: all fs.img
# -nographic disables graphic output
qemu-system-i386 $(QEMUOPTS) -display curses # -m 4G
# Exit with Ctl-A X
.PHONY: run-qemu-nogr
run-qemu-nogr: all
qemu-system-i386 $(QEMUOPTS) -nographic # -serial pty -monitor pty
.PHONY: run-qemu-gdb
run-qemu-gdb: all
@printf "==================================\n"
@printf "make run-gdb-attach\n"
@printf "==================================\n"
qemu-system-i386 $(QEMUOPTS) -S -s
.PHONY: run-gdb-attach
run-gdb-attach:
gdb -x .gdbinit
.PHONY: run-qemu-log
run-qemu-log: all
qemu-system-i386 $(QEMUOPTS) -serial stdio -no-reboot -d int,cpu_reset
# Disassemble our kernel
kernel.dis: kernel.bin
ndisasm -b 32 $< > $@
objdump-kernel-bin:
objdump -D -b binary -m i386 kernel.bin
objdump-kernel-elf:
objdump -D kernel.elf