Meaty Skeleton: Difference between revisions
Jump to navigation
Jump to search
[unchecked revision] | [unchecked revision] |
Content deleted Content added
Glauxosdever (talk | contribs) Remove -fbuiltin from the Makefiles |
Modernize Meaty Skeleton to my 2016 taste. See talk page section 2016-09-02 Changes for the full summary of changes. |
||
Line 208: | Line 208: | ||
Check for differences between the git revision used in this article and what you cloned (empty output is no difference): |
Check for differences between the git revision used in this article and what you cloned (empty output is no difference): |
||
<source lang="bash"> |
<source lang="bash"> |
||
git diff |
git diff 084d1624bedaa9f9e395f055c6bd99299bd97f58..master |
||
</source> |
</source> |
||
Line 216: | Line 215: | ||
=== kernel === |
=== kernel === |
||
==== kernel/include/kernel/vga.h ==== |
|||
<source lang="c"> |
|||
#ifndef _KERNEL_VGA_H |
|||
#define _KERNEL_VGA_H |
|||
#include <stdint.h> |
|||
enum vga_color |
|||
{ |
|||
COLOR_BLACK = 0, |
|||
COLOR_BLUE = 1, |
|||
COLOR_GREEN = 2, |
|||
COLOR_CYAN = 3, |
|||
COLOR_RED = 4, |
|||
COLOR_MAGENTA = 5, |
|||
COLOR_BROWN = 6, |
|||
COLOR_LIGHT_GREY = 7, |
|||
COLOR_DARK_GREY = 8, |
|||
COLOR_LIGHT_BLUE = 9, |
|||
COLOR_LIGHT_GREEN = 10, |
|||
COLOR_LIGHT_CYAN = 11, |
|||
COLOR_LIGHT_RED = 12, |
|||
COLOR_LIGHT_MAGENTA = 13, |
|||
COLOR_LIGHT_BROWN = 14, |
|||
COLOR_WHITE = 15, |
|||
}; |
|||
static inline uint8_t make_color(enum vga_color fg, enum vga_color bg) |
|||
{ |
|||
return fg | bg << 4; |
|||
} |
|||
static inline uint16_t make_vgaentry(char c, uint8_t color) |
|||
{ |
|||
uint16_t c16 = c; |
|||
uint16_t color16 = color; |
|||
return c16 | color16 << 8; |
|||
} |
|||
static const size_t VGA_WIDTH = 80; |
|||
static const size_t VGA_HEIGHT = 25; |
|||
static uint16_t* const VGA_MEMORY = (uint16_t*) 0xB8000; |
|||
#endif |
|||
</source> |
|||
==== kernel/include/kernel/tty.h ==== |
==== kernel/include/kernel/tty.h ==== |
||
Line 284: | Line 235: | ||
<source lang="make"> |
<source lang="make"> |
||
DEFAULT_HOST!=../default-host.sh |
|||
HOST?=DEFAULT_HOST |
|||
HOSTARCH:=$(shell ../target-triplet-to-arch.sh $(HOST)) |
|||
HOSTARCH!=../target-triplet-to-arch.sh $(HOST) |
|||
CFLAGS?=-O2 -g |
CFLAGS?=-O2 -g |
||
Line 299: | Line 251: | ||
CFLAGS:=$(CFLAGS) -ffreestanding -Wall -Wextra |
CFLAGS:=$(CFLAGS) -ffreestanding -Wall -Wextra |
||
CPPFLAGS:=$(CPPFLAGS) - |
CPPFLAGS:=$(CPPFLAGS) -D__is_kernel -Iinclude |
||
LDFLAGS:=$(LDFLAGS) |
LDFLAGS:=$(LDFLAGS) |
||
LIBS:=$(LIBS) -nostdlib -lk -lgcc |
LIBS:=$(LIBS) -nostdlib -lk -lgcc |
||
ARCHDIR |
ARCHDIR=arch/$(HOSTARCH) |
||
include $(ARCHDIR)/make.config |
include $(ARCHDIR)/make.config |
||
Line 312: | Line 264: | ||
LIBS:=$(LIBS) $(KERNEL_ARCH_LIBS) |
LIBS:=$(LIBS) $(KERNEL_ARCH_LIBS) |
||
KERNEL_OBJS=\ |
|||
OBJS:=\ |
|||
$(KERNEL_ARCH_OBJS) \ |
$(KERNEL_ARCH_OBJS) \ |
||
kernel/kernel.o \ |
kernel/kernel.o \ |
||
OBJS=\ |
|||
CRTI_OBJ:=$(ARCHDIR)/crti.o |
|||
$(ARCHDIR)/crti.o \ |
|||
CRTBEGIN_OBJ:=$(shell $(CC) $(CFLAGS) $(LDFLAGS) -print-file-name=crtbegin.o) |
|||
$(ARCHDIR)/crtbegin.o \ |
|||
CRTEND_OBJ:=$(shell $(CC) $(CFLAGS) $(LDFLAGS) -print-file-name=crtend.o) |
|||
$(KERNEL_OBJS) \ |
|||
CRTN_OBJ:=$(ARCHDIR)/crtn.o |
|||
$(ARCHDIR)/crtend.o \ |
|||
$(ARCHDIR)/crtn.o \ |
|||
LINK_LIST=\ |
|||
ALL_OUR_OBJS:=\ |
|||
$( |
$(LDFLAGS) \ |
||
$( |
$(ARCHDIR)/crti.o \ |
||
$( |
$(ARCHDIR)/crtbegin.o \ |
||
$(KERNEL_OBJS) \ |
|||
$(LIBS) \ |
|||
$(ARCHDIR)/crtend.o \ |
|||
$(ARCHDIR)/crtn.o \ |
|||
.PHONY: all clean install install-headers install-kernel |
|||
OBJ_LINK_LIST:=\ |
|||
.SUFFIXES: .o .c .S |
|||
$(CRTI_OBJ) \ |
|||
$(CRTBEGIN_OBJ) \ |
|||
$(OBJS) \ |
|||
$(CRTEND_OBJ) \ |
|||
$(CRTN_OBJ) \ |
|||
all: myos.kernel |
all: myos.kernel |
||
myos.kernel: $(OBJS) $(ARCHDIR)/linker.ld |
|||
.PHONY: all clean install install-headers install-kernel |
|||
$(CC) -T $(ARCHDIR)/linker.ld -o $@ $(CFLAGS) $(LINK_LIST) |
|||
grub-file --is-x86-multiboot myos.kernel |
|||
$(ARCHDIR)/crtbegin.o $(ARCHDIR)/crtend.o: |
|||
OBJ=`$(CC) $(CFLAGS) $(LDFLAGS) -print-file-name=$(@F)` && cp "$$OBJ" $@ |
|||
$(CC) -T $(ARCHDIR)/linker.ld -o $@ $(CFLAGS) $(OBJ_LINK_LIST) $(LDFLAGS) $(LIBS) |
|||
.c.o: |
|||
$(CC) -c $< -o $@ -std=gnu11 $(CFLAGS) $(CPPFLAGS) |
$(CC) -MD -c $< -o $@ -std=gnu11 $(CFLAGS) $(CPPFLAGS) |
||
.S.o: |
|||
$(CC) -c $< -o $@ $(CFLAGS) $(CPPFLAGS) |
$(CC) -MD -c $< -o $@ $(CFLAGS) $(CPPFLAGS) |
||
clean: |
clean: |
||
rm -f myos.kernel |
rm -f myos.kernel |
||
rm -f $(OBJS) *.o */*.o */*/*.o |
|||
rm -f $(OBJS:.o=.d) *.d */*.d */*/*.d |
|||
install: install-headers install-kernel |
install: install-headers install-kernel |
||
Line 353: | Line 311: | ||
install-headers: |
install-headers: |
||
mkdir -p $(DESTDIR)$(INCLUDEDIR) |
mkdir -p $(DESTDIR)$(INCLUDEDIR) |
||
cp - |
cp -R --preserve=timestamps include/. $(DESTDIR)$(INCLUDEDIR)/. |
||
install-kernel: myos.kernel |
install-kernel: myos.kernel |
||
mkdir -p $(DESTDIR)$(BOOTDIR) |
mkdir -p $(DESTDIR)$(BOOTDIR) |
||
cp myos.kernel $(DESTDIR)$(BOOTDIR) |
cp myos.kernel $(DESTDIR)$(BOOTDIR) |
||
-include $(OBJS:.o=.d) |
|||
</source> |
</source> |
||
Line 363: | Line 323: | ||
<source lang="c"> |
<source lang="c"> |
||
#include <stddef.h> |
|||
#include <stdint.h> |
|||
#include <string.h> |
|||
#include <stdio.h> |
#include <stdio.h> |
||
#include <kernel/tty.h> |
#include <kernel/tty.h> |
||
void |
void kernel_main(void) { |
||
{ |
|||
terminal_initialize(); |
terminal_initialize(); |
||
} |
|||
void kernel_main(void) |
|||
{ |
|||
printf("Hello, kernel World!\n"); |
printf("Hello, kernel World!\n"); |
||
} |
} |
||
Line 390: | Line 342: | ||
#include <kernel/tty.h> |
#include <kernel/tty.h> |
||
#include <kernel/vga.h> |
|||
#include "vga.h" |
|||
size_t terminal_row; |
|||
size_t terminal_column; |
|||
uint8_t terminal_color; |
|||
uint16_t* terminal_buffer; |
|||
static const size_t VGA_WIDTH = 80; |
|||
void terminal_initialize(void) |
|||
static const size_t VGA_HEIGHT = 25; |
|||
{ |
|||
static uint16_t* const VGA_MEMORY = (uint16_t*) 0xB8000; |
|||
static size_t terminal_row; |
|||
static size_t terminal_column; |
|||
static uint8_t terminal_color; |
|||
static uint16_t* terminal_buffer; |
|||
void terminal_initialize(void) { |
|||
terminal_row = 0; |
terminal_row = 0; |
||
terminal_column = 0; |
terminal_column = 0; |
||
terminal_color = |
terminal_color = vga_entry_color(VGA_COLOR_LIGHT_GREY, VGA_COLOR_BLACK); |
||
terminal_buffer = VGA_MEMORY; |
terminal_buffer = VGA_MEMORY; |
||
for ( |
for (size_t y = 0; y < VGA_HEIGHT; y++) { |
||
for (size_t x = 0; x < VGA_WIDTH; x++) { |
|||
{ |
|||
for ( size_t x = 0; x < VGA_WIDTH; x++ ) |
|||
{ |
|||
const size_t index = y * VGA_WIDTH + x; |
const size_t index = y * VGA_WIDTH + x; |
||
terminal_buffer[index] = |
terminal_buffer[index] = vga_entry(' ', terminal_color); |
||
} |
} |
||
} |
} |
||
} |
} |
||
void terminal_setcolor(uint8_t color) |
void terminal_setcolor(uint8_t color) { |
||
{ |
|||
terminal_color = color; |
terminal_color = color; |
||
} |
} |
||
void terminal_putentryat(char c, uint8_t color, size_t x, size_t y) |
void terminal_putentryat(unsigned char c, uint8_t color, size_t x, size_t y) { |
||
{ |
|||
const size_t index = y * VGA_WIDTH + x; |
const size_t index = y * VGA_WIDTH + x; |
||
terminal_buffer[index] = |
terminal_buffer[index] = vga_entry(c, color); |
||
} |
} |
||
void terminal_putchar(char c) |
void terminal_putchar(char c) { |
||
unsigned char uc = c; |
|||
{ |
|||
terminal_putentryat( |
terminal_putentryat(uc, terminal_color, terminal_column, terminal_row); |
||
if ( |
if (++terminal_column == VGA_WIDTH) { |
||
{ |
|||
terminal_column = 0; |
terminal_column = 0; |
||
if ( |
if (++terminal_row == VGA_HEIGHT) |
||
{ |
|||
terminal_row = 0; |
terminal_row = 0; |
||
} |
|||
} |
} |
||
} |
} |
||
void terminal_write(const char* data, size_t size) |
void terminal_write(const char* data, size_t size) { |
||
for (size_t i = 0; i < size; i++) |
|||
{ |
|||
for ( size_t i = 0; i < size; i++ ) |
|||
terminal_putchar(data[i]); |
terminal_putchar(data[i]); |
||
} |
} |
||
void terminal_writestring(const char* data) |
void terminal_writestring(const char* data) { |
||
{ |
|||
terminal_write(data, strlen(data)); |
terminal_write(data, strlen(data)); |
||
} |
} |
||
Line 462: | Line 409: | ||
ret |
ret |
||
</pre> |
</pre> |
||
==== kernel/arch/i386/vga.h ==== |
|||
<source lang="c"> |
|||
#ifndef ARCH_I386_VGA_H |
|||
#define ARCH_I386_VGA_H |
|||
#include <stdint.h> |
|||
enum vga_color { |
|||
VGA_COLOR_BLACK = 0, |
|||
VGA_COLOR_BLUE = 1, |
|||
VGA_COLOR_GREEN = 2, |
|||
VGA_COLOR_CYAN = 3, |
|||
VGA_COLOR_RED = 4, |
|||
VGA_COLOR_MAGENTA = 5, |
|||
VGA_COLOR_BROWN = 6, |
|||
VGA_COLOR_LIGHT_GREY = 7, |
|||
VGA_COLOR_DARK_GREY = 8, |
|||
VGA_COLOR_LIGHT_BLUE = 9, |
|||
VGA_COLOR_LIGHT_GREEN = 10, |
|||
VGA_COLOR_LIGHT_CYAN = 11, |
|||
VGA_COLOR_LIGHT_RED = 12, |
|||
VGA_COLOR_LIGHT_MAGENTA = 13, |
|||
VGA_COLOR_LIGHT_BROWN = 14, |
|||
VGA_COLOR_WHITE = 15, |
|||
}; |
|||
static inline uint8_t vga_entry_color(enum vga_color fg, enum vga_color bg) { |
|||
return fg | bg << 4; |
|||
} |
|||
static inline uint16_t vga_entry(unsigned char uc, uint8_t color) { |
|||
return (uint16_t) uc | (uint16_t) color << 8; |
|||
} |
|||
#endif |
|||
</source> |
|||
==== kernel/arch/i386/make.config ==== |
==== kernel/arch/i386/make.config ==== |
||
<source lang="make"> |
<source lang="make"> |
||
KERNEL_ARCH_CFLAGS |
KERNEL_ARCH_CFLAGS= |
||
KERNEL_ARCH_CPPFLAGS |
KERNEL_ARCH_CPPFLAGS= |
||
KERNEL_ARCH_LDFLAGS |
KERNEL_ARCH_LDFLAGS= |
||
KERNEL_ARCH_LIBS |
KERNEL_ARCH_LIBS= |
||
KERNEL_ARCH_OBJS |
KERNEL_ARCH_OBJS=\ |
||
$(ARCHDIR)/boot.o \ |
$(ARCHDIR)/boot.o \ |
||
$(ARCHDIR)/tty.o \ |
$(ARCHDIR)/tty.o \ |
||
Line 537: | Line 522: | ||
*(COMMON) |
*(COMMON) |
||
*(.bss) |
*(.bss) |
||
*(.bootstrap_stack) |
|||
} |
} |
||
Line 548: | Line 532: | ||
<pre> |
<pre> |
||
# Declare constants |
# Declare constants for the multiboot header. |
||
.set ALIGN, 1<<0 # align loaded modules on page boundaries |
.set ALIGN, 1<<0 # align loaded modules on page boundaries |
||
.set MEMINFO, 1<<1 # provide memory map |
.set MEMINFO, 1<<1 # provide memory map |
||
Line 563: | Line 547: | ||
# Reserve a stack for the initial thread. |
# Reserve a stack for the initial thread. |
||
.section . |
.section .bss |
||
.align 16 |
|||
stack_bottom: |
stack_bottom: |
||
.skip 16384 # 16 KiB |
.skip 16384 # 16 KiB |
||
Line 574: | Line 559: | ||
_start: |
_start: |
||
movl $stack_top, %esp |
movl $stack_top, %esp |
||
# Initialize the core kernel before running the global constructors. |
|||
call kernel_early |
|||
# Call the global constructors. |
# Call the global constructors. |
||
Line 586: | Line 568: | ||
# Hang if kernel_main unexpectedly returns. |
# Hang if kernel_main unexpectedly returns. |
||
cli |
cli |
||
1: hlt |
|||
.Lhang: |
|||
jmp 1b |
|||
hlt |
|||
jmp .Lhang |
|||
.size _start, . - _start |
.size _start, . - _start |
||
</pre> |
</pre> |
||
Line 595: | Line 576: | ||
<pre> |
<pre> |
||
*. |
*.d |
||
*.kernel |
*.kernel |
||
*.o |
|||
</pre> |
</pre> |
||
Line 635: | Line 617: | ||
#include <sys/cdefs.h> |
#include <sys/cdefs.h> |
||
#define EOF (-1) |
|||
#ifdef __cplusplus |
#ifdef __cplusplus |
||
Line 687: | Line 671: | ||
<source lang="make"> |
<source lang="make"> |
||
DEFAULT_HOST!=../default-host.sh |
|||
HOST?=DEFAULT_HOST |
|||
HOSTARCH:=$(shell ../target-triplet-to-arch.sh $(HOST)) |
|||
HOSTARCH!=../target-triplet-to-arch.sh $(HOST) |
|||
CFLAGS?=-O2 -g |
CFLAGS?=-O2 -g |
||
Line 701: | Line 686: | ||
LIBDIR?=$(EXEC_PREFIX)/lib |
LIBDIR?=$(EXEC_PREFIX)/lib |
||
CFLAGS:=$(CFLAGS) -Wall -Wextra |
CFLAGS:=$(CFLAGS) -ffreestanding -Wall -Wextra |
||
CPPFLAGS:=$(CPPFLAGS) - |
CPPFLAGS:=$(CPPFLAGS) -D__is_libc -Iinclude |
||
LIBK_CFLAGS:=$(CFLAGS) |
LIBK_CFLAGS:=$(CFLAGS) |
||
LIBK_CPPFLAGS:=$(CPPFLAGS) - |
LIBK_CPPFLAGS:=$(CPPFLAGS) -D__is_libk |
||
ARCHDIR |
ARCHDIR=arch/$(HOSTARCH) |
||
include $(ARCHDIR)/make.config |
include $(ARCHDIR)/make.config |
||
Line 715: | Line 700: | ||
LIBK_CPPFLAGS:=$(LIBK_CPPFLAGS) $(KERNEL_ARCH_CPPFLAGS) |
LIBK_CPPFLAGS:=$(LIBK_CPPFLAGS) $(KERNEL_ARCH_CPPFLAGS) |
||
FREEOBJS |
FREEOBJS=\ |
||
$(ARCH_FREEOBJS) \ |
$(ARCH_FREEOBJS) \ |
||
stdio/printf.o \ |
stdio/printf.o \ |
||
Line 727: | Line 712: | ||
string/strlen.o \ |
string/strlen.o \ |
||
HOSTEDOBJS |
HOSTEDOBJS=\ |
||
$(ARCH_HOSTEDOBJS) \ |
$(ARCH_HOSTEDOBJS) \ |
||
OBJS |
OBJS=\ |
||
$(FREEOBJS) \ |
$(FREEOBJS) \ |
||
$(HOSTEDOBJS) \ |
$(HOSTEDOBJS) \ |
||
LIBK_OBJS |
LIBK_OBJS=$(FREEOBJS:.o=.libk.o) |
||
BINARIES=libc.a |
#BINARIES=libc.a libk.a # Not ready for libc yet. |
||
BINARIES=libk.a |
|||
all: $(BINARIES) |
|||
.PHONY: all clean install install-headers install-libs |
.PHONY: all clean install install-headers install-libs |
||
.SUFFIXES: .o .libk.o .c .S |
|||
all: $(BINARIES) |
|||
libc.a: $(OBJS) |
libc.a: $(OBJS) |
||
$(AR) rcs $@ $(OBJS) |
$(AR) rcs $@ $(OBJS) |
||
libg.a: |
|||
$(AR) rcs $@ |
|||
libk.a: $(LIBK_OBJS) |
libk.a: $(LIBK_OBJS) |
||
$(AR) rcs $@ $(LIBK_OBJS) |
$(AR) rcs $@ $(LIBK_OBJS) |
||
.c.o: |
|||
$(CC) -c $< -o $@ -std=gnu11 $(CFLAGS) $(CPPFLAGS) |
$(CC) -MD -c $< -o $@ -std=gnu11 $(CFLAGS) $(CPPFLAGS) |
||
.c.S: |
|||
$(CC) -c $< -o $@ $(CFLAGS) $(CPPFLAGS) |
$(CC) -MD -c $< -o $@ $(CFLAGS) $(CPPFLAGS) |
||
.c.libk.o: |
|||
$(CC) -c $< -o $@ -std=gnu11 $(LIBK_CFLAGS) $(LIBK_CPPFLAGS) |
$(CC) -MD -c $< -o $@ -std=gnu11 $(LIBK_CFLAGS) $(LIBK_CPPFLAGS) |
||
.S.libk.o: |
|||
$(CC) -c $< -o $@ $(LIBK_CFLAGS) $(LIBK_CPPFLAGS) |
$(CC) -MD -c $< -o $@ $(LIBK_CFLAGS) $(LIBK_CPPFLAGS) |
||
clean: |
clean: |
||
rm -f $(BINARIES |
rm -f $(BINARIES) *.a |
||
rm -f $(OBJS) $(LIBK_OBJS) *.o */*.o */*/*.o |
|||
rm -f $(OBJS:.o=.d) $(LIBK_OBJS:.o=.d) *.d */*.d */*/*.d |
|||
install: install-headers install-libs |
install: install-headers install-libs |
||
Line 770: | Line 756: | ||
install-headers: |
install-headers: |
||
mkdir -p $(DESTDIR)$(INCLUDEDIR) |
mkdir -p $(DESTDIR)$(INCLUDEDIR) |
||
cp - |
cp -R --preserve=timestamps include/. $(DESTDIR)$(INCLUDEDIR)/. |
||
install-libs: $(BINARIES) |
install-libs: $(BINARIES) |
||
mkdir -p $(DESTDIR)$(LIBDIR) |
mkdir -p $(DESTDIR)$(LIBDIR) |
||
cp $(BINARIES) $(DESTDIR)$(LIBDIR) |
cp $(BINARIES) $(DESTDIR)$(LIBDIR) |
||
-include $(OBJS:.o=.d) |
|||
-include $(LIBK_OBJS:.o=.d) |
|||
</source> |
</source> |
||
Line 784: | Line 773: | ||
__attribute__((__noreturn__)) |
__attribute__((__noreturn__)) |
||
void abort(void) |
void abort(void) { |
||
#if defined(__is_libk) |
|||
{ |
|||
// TODO: Add proper kernel panic. |
// TODO: Add proper kernel panic. |
||
printf(" |
printf("kernel: panic: abort()\n"); |
||
#else |
|||
while ( 1 ) { } |
|||
// TODO: Abnormally terminate the process as if by SIGABRT. |
|||
printf("abort()\n"); |
|||
#endif |
|||
while (1) { } |
|||
__builtin_unreachable(); |
__builtin_unreachable(); |
||
} |
} |
||
Line 798: | Line 791: | ||
#include <string.h> |
#include <string.h> |
||
void* memmove(void* dstptr, const void* srcptr, size_t size) |
void* memmove(void* dstptr, const void* srcptr, size_t size) { |
||
{ |
|||
unsigned char* dst = (unsigned char*) dstptr; |
unsigned char* dst = (unsigned char*) dstptr; |
||
const unsigned char* src = (const unsigned char*) srcptr; |
const unsigned char* src = (const unsigned char*) srcptr; |
||
if ( |
if (dst < src) { |
||
for ( |
for (size_t i = 0; i < size; i++) |
||
dst[i] = src[i]; |
dst[i] = src[i]; |
||
else |
} else { |
||
for ( |
for (size_t i = size; i != 0; i--) |
||
dst[i-1] = src[i-1]; |
dst[i-1] = src[i-1]; |
||
} |
|||
return dstptr; |
return dstptr; |
||
} |
} |
||
Line 817: | Line 810: | ||
#include <string.h> |
#include <string.h> |
||
size_t strlen(const char* |
size_t strlen(const char* str) { |
||
size_t len = 0; |
|||
{ |
|||
while (str[len]) |
|||
size_t result = 0; |
|||
len++; |
|||
while ( string[result] ) |
|||
return len; |
|||
result++; |
|||
return result; |
|||
} |
} |
||
</source> |
</source> |
||
Line 831: | Line 823: | ||
#include <string.h> |
#include <string.h> |
||
int memcmp(const void* aptr, const void* bptr, size_t size) |
int memcmp(const void* aptr, const void* bptr, size_t size) { |
||
{ |
|||
const unsigned char* a = (const unsigned char*) aptr; |
const unsigned char* a = (const unsigned char*) aptr; |
||
const unsigned char* b = (const unsigned char*) bptr; |
const unsigned char* b = (const unsigned char*) bptr; |
||
for ( |
for (size_t i = 0; i < size; i++) { |
||
if ( |
if (a[i] < b[i]) |
||
return -1; |
return -1; |
||
else if ( |
else if (b[i] < a[i]) |
||
return 1; |
return 1; |
||
} |
|||
return 0; |
return 0; |
||
} |
} |
||
Line 849: | Line 841: | ||
#include <string.h> |
#include <string.h> |
||
void* memset(void* bufptr, int value, size_t size) |
void* memset(void* bufptr, int value, size_t size) { |
||
{ |
|||
unsigned char* buf = (unsigned char*) bufptr; |
unsigned char* buf = (unsigned char*) bufptr; |
||
for ( |
for (size_t i = 0; i < size; i++) |
||
buf[i] = (unsigned char) value; |
buf[i] = (unsigned char) value; |
||
return bufptr; |
return bufptr; |
||
Line 863: | Line 854: | ||
#include <string.h> |
#include <string.h> |
||
void* memcpy(void* restrict dstptr, const void* restrict srcptr, size_t size) |
void* memcpy(void* restrict dstptr, const void* restrict srcptr, size_t size) { |
||
{ |
|||
unsigned char* dst = (unsigned char*) dstptr; |
unsigned char* dst = (unsigned char*) dstptr; |
||
const unsigned char* src = (const unsigned char*) srcptr; |
const unsigned char* src = (const unsigned char*) srcptr; |
||
for ( |
for (size_t i = 0; i < size; i++) |
||
dst[i] = src[i]; |
dst[i] = src[i]; |
||
return dstptr; |
return dstptr; |
||
Line 878: | Line 868: | ||
#include <stdio.h> |
#include <stdio.h> |
||
int puts(const char* string) |
int puts(const char* string) { |
||
{ |
|||
return printf("%s\n", string); |
return printf("%s\n", string); |
||
} |
} |
||
Line 889: | Line 878: | ||
#include <stdio.h> |
#include <stdio.h> |
||
#if defined( |
#if defined(__is_libk) |
||
#include <kernel/tty.h> |
#include <kernel/tty.h> |
||
#endif |
#endif |
||
int putchar(int ic) |
int putchar(int ic) { |
||
#if defined(__is_libk) |
|||
{ |
|||
#if defined(__is_myos_kernel) |
|||
char c = (char) ic; |
char c = (char) ic; |
||
terminal_write(&c, sizeof(c)); |
terminal_write(&c, sizeof(c)); |
||
#else |
#else |
||
// TODO: |
// TODO: Implement stdio and the write system call. |
||
#endif |
#endif |
||
return ic; |
return ic; |
||
Line 908: | Line 896: | ||
<source lang="c"> |
<source lang="c"> |
||
#include <limits.h> |
|||
#include <stdbool.h> |
#include <stdbool.h> |
||
#include <stdarg.h> |
#include <stdarg.h> |
||
Line 913: | Line 902: | ||
#include <string.h> |
#include <string.h> |
||
static |
static bool print(const char* data, size_t length) { |
||
const unsigned char* bytes = (const unsigned char*) data; |
|||
{ |
|||
for ( |
for (size_t i = 0; i < length; i++) |
||
if (putchar(bytes[i]) == EOF) |
|||
putchar((int) ((const unsigned char*) data)[i]); |
|||
return false; |
|||
return true; |
|||
} |
} |
||
int printf(const char* restrict format, ...) |
int printf(const char* restrict format, ...) { |
||
{ |
|||
va_list parameters; |
va_list parameters; |
||
va_start(parameters, format); |
va_start(parameters, format); |
||
int written = 0; |
int written = 0; |
||
size_t amount; |
|||
bool rejected_bad_specifier = false; |
|||
while ( |
while (*format != '\0') { |
||
size_t maxrem = INT_MAX - written; |
|||
{ |
|||
if ( *format != '%' ) |
|||
if (format[0] != '%' || format[1] == '%') { |
|||
{ |
|||
if (format[0] == '%') |
|||
print_c: |
|||
format++; |
|||
size_t amount = 1; |
|||
while (format[amount] && format[amount] != '%') |
|||
amount++; |
amount++; |
||
if (maxrem < amount) { |
|||
// TODO: Set errno to EOVERFLOW. |
|||
return -1; |
|||
} |
|||
if (!print(format, amount)) |
|||
return -1; |
|||
format += amount; |
format += amount; |
||
written += amount; |
written += amount; |
||
Line 942: | Line 936: | ||
} |
} |
||
const char* format_begun_at = format; |
const char* format_begun_at = format++; |
||
if ( |
if (*format == 'c') { |
||
goto print_c; |
|||
if ( rejected_bad_specifier ) |
|||
{ |
|||
incomprehensible_conversion: |
|||
rejected_bad_specifier = true; |
|||
format = format_begun_at; |
|||
goto print_c; |
|||
} |
|||
if ( *format == 'c' ) |
|||
{ |
|||
format++; |
format++; |
||
char c = (char) va_arg(parameters, int /* char promotes to int */); |
char c = (char) va_arg(parameters, int /* char promotes to int */); |
||
if (!maxrem) { |
|||
print(&c, sizeof(c)); |
|||
// TODO: Set errno to EOVERFLOW. |
|||
} |
|||
return -1; |
|||
else if ( *format == 's' ) |
|||
} |
|||
if (!print(&c, sizeof(c))) |
|||
return -1; |
|||
written++; |
|||
} else if (*format == 's') { |
|||
format++; |
format++; |
||
const char* |
const char* str = va_arg(parameters, const char*); |
||
size_t len = strlen(str); |
|||
if (maxrem < len) { |
|||
} |
|||
// TODO: Set errno to EOVERFLOW. |
|||
else |
|||
return -1; |
|||
{ |
|||
} |
|||
goto incomprehensible_conversion; |
|||
if (!print(str, len)) |
|||
return -1; |
|||
written += len; |
|||
} else { |
|||
format = format_begun_at; |
|||
size_t len = strlen(format); |
|||
if (maxrem < len) { |
|||
// TODO: Set errno to EOVERFLOW. |
|||
return -1; |
|||
} |
|||
if (!print(format, len)) |
|||
return -1; |
|||
written += len; |
|||
format += len; |
|||
} |
} |
||
} |
} |
||
va_end(parameters); |
va_end(parameters); |
||
return written; |
return written; |
||
} |
} |
||
Line 982: | Line 981: | ||
<source lang="make"> |
<source lang="make"> |
||
ARCH_CFLAGS |
ARCH_CFLAGS= |
||
ARCH_CPPFLAGS |
ARCH_CPPFLAGS= |
||
KERNEL_ARCH_CFLAGS |
KERNEL_ARCH_CFLAGS= |
||
KERNEL_ARCH_CPPFLAGS |
KERNEL_ARCH_CPPFLAGS= |
||
ARCH_FREEOBJS |
ARCH_FREEOBJS=\ |
||
ARCH_HOSTEDOBJS |
ARCH_HOSTEDOBJS=\ |
||
</source> |
</source> |
||
Line 995: | Line 994: | ||
<pre> |
<pre> |
||
*.o |
|||
*.a |
*.a |
||
*.d |
|||
*.o |
|||
</pre> |
</pre> |
||
Line 1,011: | Line 1,011: | ||
for PROJECT in $PROJECTS; do |
for PROJECT in $PROJECTS; do |
||
DESTDIR="$ |
(cd $PROJECT && DESTDIR="$SYSROOT" $MAKE install) |
||
done |
done |
||
</source> |
</source> |
||
Line 1,028: | Line 1,028: | ||
for PROJECT in $PROJECTS; do |
for PROJECT in $PROJECTS; do |
||
$ |
(cd $PROJECT && $MAKE clean) |
||
done |
done |
||
rm - |
rm -rf sysroot |
||
rm - |
rm -rf isodir |
||
rm - |
rm -rf myos.iso |
||
</source> |
</source> |
||
Line 1,064: | Line 1,064: | ||
# Configure the cross-compiler to use the desired system root. |
# Configure the cross-compiler to use the desired system root. |
||
export |
export SYSROOT="$(pwd)/sysroot" |
||
export CC="$CC --sysroot=$SYSROOT" |
|||
# Work around that the -elf gcc targets doesn't have a system include directory |
# Work around that the -elf gcc targets doesn't have a system include directory |
||
# because |
# because it was configured with --without-headers rather than --with-sysroot. |
||
if echo "$HOST" | grep -Eq -- '-elf($|-)'; then |
if echo "$HOST" | grep -Eq -- '-elf($|-)'; then |
||
export CC="$CC -isystem=$INCLUDEDIR" |
export CC="$CC -isystem=$INCLUDEDIR" |
||
Line 1,092: | Line 1,093: | ||
. ./config.sh |
. ./config.sh |
||
mkdir -p |
mkdir -p "$SYSROOT" |
||
for PROJECT in $SYSTEM_HEADER_PROJECTS; do |
for PROJECT in $SYSTEM_HEADER_PROJECTS; do |
||
DESTDIR="$ |
(cd $PROJECT && DESTDIR="$SYSROOT" $MAKE install-headers) |
||
done |
done |
||
</source> |
</source> |