From 94ca8c935fb089af62b50d076e0370f7d55cdbef Mon Sep 17 00:00:00 2001 From: Tom-on64 Date: Sun, 5 Jan 2025 18:20:15 +0100 Subject: [PATCH] Added AMAZING boot menu to KBOOT --- boot/stage1/bootsect.s | 7 +- boot/stage1/gdt.s | 4 +- boot/stage2/attr.h | 9 +++ boot/stage2/disk.c | 24 +++++++ boot/stage2/disk.h | 35 ++++++++++ boot/stage2/entry.c | 97 +++++++++++++++++++++++++++- boot/stage2/kbd.c | 12 ++++ boot/stage2/kbd.h | 19 ++++++ boot/stage2/linker.ld | 13 ++-- boot/stage2/menu.c | 73 +++++++++++++++++++++ boot/stage2/menu.h | 33 ++++++++++ boot/stage2/port.h | 33 ++++++++++ boot/stage2/stdarg.h | 10 +++ boot/stage2/stdint.h | 22 +++++++ boot/stage2/stdio.c | 141 +++++++++++++++++++++++++++++++++++++++++ boot/stage2/stdio.h | 25 ++++++++ boot/stage2/string.c | 74 +++++++++++++++++++++ boot/stage2/string.h | 15 +++++ defaults.mk | 2 +- docs/coding-style.txt | 16 +++++ libc/string/itoa.c | 1 + makefile | 2 +- 22 files changed, 651 insertions(+), 16 deletions(-) create mode 100644 boot/stage2/attr.h create mode 100644 boot/stage2/disk.c create mode 100644 boot/stage2/disk.h create mode 100644 boot/stage2/kbd.c create mode 100644 boot/stage2/kbd.h create mode 100644 boot/stage2/menu.c create mode 100644 boot/stage2/menu.h create mode 100644 boot/stage2/port.h create mode 100644 boot/stage2/stdarg.h create mode 100644 boot/stage2/stdint.h create mode 100644 boot/stage2/stdio.c create mode 100644 boot/stage2/stdio.h create mode 100644 boot/stage2/string.c create mode 100644 boot/stage2/string.h diff --git a/boot/stage1/bootsect.s b/boot/stage1/bootsect.s index 354f227..2de8a2f 100644 --- a/boot/stage1/bootsect.s +++ b/boot/stage1/bootsect.s @@ -11,6 +11,7 @@ jmp short .bpb_end nop ; FAT32 Bios Parameter Block +; Some BIOSes mess with it so we just leave it blank .bpb: .bpb_oem_id: db "KERN " .bpb_sector_size: dw 0 @@ -115,17 +116,17 @@ err: [bits 32] ; Protected mode entry vector vector: - mov eax, 0x10 + mov ax, 0x10 mov ds, ax mov es, ax mov fs, ax mov gs, ax mov ss, ax - and edx, 0xff + and edx, 0xff ; Still should be boot drive number ; Call stage 2 bootloader - call 0x70000 + call code_seg:0x70000 ; Padding and boot signature times 510-($-$$) db 0 diff --git a/boot/stage1/gdt.s b/boot/stage1/gdt.s index 192fde7..edade70 100644 --- a/boot/stage1/gdt.s +++ b/boot/stage1/gdt.s @@ -24,5 +24,5 @@ gdtp: dd gdt ; Pointer ; Segments -code_seg equ gdt.code_desc - gdt -data_seg equ gdt.data_desc - gdt +code_seg: equ gdt.code_desc - gdt +data_seg: equ gdt.data_desc - gdt diff --git a/boot/stage2/attr.h b/boot/stage2/attr.h new file mode 100644 index 0000000..870eeeb --- /dev/null +++ b/boot/stage2/attr.h @@ -0,0 +1,9 @@ +#ifndef ATTR_H +#define ATTR_H + +#define __packed __attribute__((packed)) +#define __naked __attribute__((naked)) +#define __section(_sect) __attribute__((section(_sect))) +#define noreturn __attribute__((noreturn)) + +#endif diff --git a/boot/stage2/disk.c b/boot/stage2/disk.c new file mode 100644 index 0000000..b46267d --- /dev/null +++ b/boot/stage2/disk.c @@ -0,0 +1,24 @@ +#include "stdint.h" +#include "port.h" +#include "disk.h" + +void readSectors(uint32_t lba, size_t count, void* dst) { + outb(PIO_PORT + 6, ((lba >> 24) & 0x0f) | 0xe0); + outb(PIO_PORT + 2, count); + outb(PIO_PORT + 3, lba & 0xff); + outb(PIO_PORT + 4, (lba >> 8) & 0xff); + outb(PIO_PORT + 5, (lba >> 16) & 0xff); + outb(PIO_PORT + 7, PIO_CMD_READ); + + uint16_t* buf = (uint16_t*)dst; + + for (size_t i = 0; i < count; i++) { + while (inb(PIO_PORT + 7) & (1 << 7)); // Wait until BSY is cleared + for (size_t j = 0; j < SECTOR_SIZE / 2; j++) *buf++ = inw(PIO_PORT); + for (uint8_t wait = 0; wait < 4; wait++) inb(PIO_ALT_STATUS); + } +} + +/* TODO */ +void writeSectors(uint32_t lba, size_t count, void* src) {} + diff --git a/boot/stage2/disk.h b/boot/stage2/disk.h new file mode 100644 index 0000000..0c36bab --- /dev/null +++ b/boot/stage2/disk.h @@ -0,0 +1,35 @@ +#ifndef DISK_H +#define DISK_H + +#include "stdint.h" +#include "attr.h" + +#define SECTOR_SIZE 512 +#define PIO_PORT 0x1f0 +#define PIO_ALT_STATUS 0x3f6 +#define PIO_MASTER 0xa0 +#define PIO_CMD_READ 0x20 +#define PIO_CMD_WRITE 0x30 +#define PIO_CMD_FLUSH 0 // TODO + +#define BOOTABLE 0x80 + +struct partition { + uint8_t bootable; + uint8_t startCHS[3]; + uint8_t type; + uint8_t endCHS[3]; + uint32_t startLBA; + uint32_t size; +} __packed; + +struct MBR { + uint8_t bootstrap[446]; + struct partition partitions[4]; + uint16_t signature; +} __packed; + +void readSectors(uint32_t lba, size_t count, void* buffer); +void writeSectors(uint32_t lba, size_t count, void* buffer); + +#endif diff --git a/boot/stage2/entry.c b/boot/stage2/entry.c index b82e250..6e7c91d 100644 --- a/boot/stage2/entry.c +++ b/boot/stage2/entry.c @@ -1,3 +1,98 @@ -void entry() { +#include "stdint.h" +#include "stdio.h" +#include "attr.h" +#include "disk.h" +#include "menu.h" +#include "kbd.h" + +void drawPartitions(struct MBR* mbr, uint8_t sel); +void partitonInfo(struct partition* part); + +__section("entry") +noreturn void main() { + keyboardInit(); + + struct MBR mbr; + readSectors(0, 1, &mbr); + + // Select bootable partition by default + uint8_t selected = 0; + for (size_t i = 0; i < 4; i++) { + if (mbr.partitions[i].bootable != BOOTABLE) continue; + selected = i; + break; + } + + // Initial draw + setAttr(0x0f); + cls(); + hideCursor(); + rect(0, 0, COLS, ROWS); + hline(0, 2, COLS); + setAttr(0x02); + text(COLS / 2, 1, "KBOOT"); + drawPartitions(&mbr, selected); + partitonInfo(&mbr.partitions[selected]); + + while (1) { + // Check for up/down arrow keys or enter + uint8_t scancode = getScancode(); + if (scancode == SC_ENTER) { // Boot selected + if (mbr.partitions[selected].type != 0) break; + + // Don't allow booting an unused partition + setAttr(0x4f); + text(COLS / 2, ROWS / 2 + 6, "Unused Partition"); + } else if (scancode != SC_EXTENDED) continue; // Not an arrow key + + scancode = getScancode(); + if (scancode == SCE_ARROW_UP) selected--; + else if (scancode == SCE_ARROW_DOWN) selected++; + else continue; + + if (selected == 0xff) selected = 3; + else if (selected == 4) selected = 0; + + // Redraw + drawPartitions(&mbr, selected); + partitonInfo(&mbr.partitions[selected]); + } + + setAttr(0x0f); + cls(); + showCursor(); + printf("Booting from Partition %d...", selected); + while (1); } + +void drawPartitions(struct MBR* mbr, uint8_t sel) { + uint32_t basey = ROWS / 2 - 2; + for (size_t i = 0; i < 4; i++) { + if (i == sel) setAttr(0xf0); + else if (mbr->partitions[i].type == 0) setAttr(0x04); + else setAttr(0x0f); + + text(COLS / 2, basey + i, " [ Partition %d ] ", i+1); + } +} + +void partitonInfo(struct partition* part) { + uint32_t basey = ROWS / 2 + 6; + setAttr(0x02); + + // Clear previous text + fill(1, basey, COLS - 2, 3, '\0'); + + if (part->type == 0) { + text(COLS / 2, basey, "Unused Partition"); + return; + } + + text(COLS / 2, basey, "Type: %02x%s", part->type, + (part->bootable == BOOTABLE) ? " Bootable" : ""); + text(COLS / 2, basey + 1, "Start LBA: %d; End LBA: %d", + part->startLBA, part->startLBA + part->size); + text(COLS / 2, basey + 2, "Length: 0x%x", part->size); +} + diff --git a/boot/stage2/kbd.c b/boot/stage2/kbd.c new file mode 100644 index 0000000..111db1b --- /dev/null +++ b/boot/stage2/kbd.c @@ -0,0 +1,12 @@ +#include "stdint.h" +#include "port.h" +#include "kbd.h" + +// TODO: Maybe do some setup? +int keyboardInit() { return 0; } + +uint8_t getScancode() { + while (inb(PS2_STAT_PORT) & 0x01 == 0); + return inb(PS2_DATA_PORT); +} + diff --git a/boot/stage2/kbd.h b/boot/stage2/kbd.h new file mode 100644 index 0000000..f197099 --- /dev/null +++ b/boot/stage2/kbd.h @@ -0,0 +1,19 @@ +#ifndef _KBD_H +#define _KBD_H + +#include "stdint.h" + +#define PS2_DATA_PORT 0x60 +#define PS2_STAT_PORT 0x64 + +// Scancodes +#define SC_ENTER 0x1C +#define SC_EXTENDED 0xE0 +// Extended scancodes +#define SCE_ARROW_UP 0x48 +#define SCE_ARROW_DOWN 0x50 + +int keyboardInit(); +uint8_t getScancode(); + +#endif diff --git a/boot/stage2/linker.ld b/boot/stage2/linker.ld index 55e53c4..6e83aea 100644 --- a/boot/stage2/linker.ld +++ b/boot/stage2/linker.ld @@ -1,27 +1,24 @@ OUTPUT_FORMAT(binary) -ENTRY(entry) +OUTPUT_ARCH(i386) SECTIONS { - /* Will be loaded at 0x70000 */ . = 0x70000; .text : { + *(entry) *(.text) - *(.text.*) + } + + .rodata : { *(.rodata) - *(.rodata.*) } .data : { *(.data) - *(.data.*) } .bss : { *(COMMON) *(.bss) - *(.bss.*) } - - _end = .; } diff --git a/boot/stage2/menu.c b/boot/stage2/menu.c new file mode 100644 index 0000000..ff23a24 --- /dev/null +++ b/boot/stage2/menu.c @@ -0,0 +1,73 @@ +#include "stdarg.h" +#include "stdint.h" +#include "string.h" +#include "stdio.h" +#include "menu.h" + +/* + * The reason we subtract one from the width and height (or length) is because + * we use the (in this example) width to offset from the (in this example) x + * position. If something has a width of 1 character, the end of it should be + * at 'x + w', so if 'w' were 1, it would be off by one. Therefore we subtract + * one from the given dimensions. + */ + +void rect(uint32_t x, uint32_t y, uint32_t _w, uint32_t _h) { + if (_w < 2 || _h < 2) return; + uint32_t w = _w - 1; + uint32_t h = _h - 1; + + // Top + putat(y, x, CORNER_TL); + for (size_t dx = 1; dx < w; dx++) putat(y, x + dx, LINE_H); + putat(y, x + w, CORNER_TR); + + // Sides + for (size_t dy = 1; dy < h; dy++) { + putat(y + dy, x, LINE_V); + putat(y + dy, x + w, LINE_V); + } + + // Bottom + putat(y + h, x, CORNER_BL); + for (size_t dx = 1; dx < w; dx++) putat(y + h, x + dx, LINE_H); + putat(y + h, x + w, CORNER_BR); +} + +void fill(uint32_t x, uint32_t y, uint32_t w, uint32_t h, char c) { + // We don't add one to the dimensions here + for (size_t dy = 0; dy < h; dy++) { + for (size_t dx = 0; dx < w; dx++) { + putat(y + dy, x + dx, c); + } + } +} + +void hline(uint32_t x, uint32_t y, uint32_t _len) { + uint32_t len = _len - 1; + putat(y, x, LINE_T_RIGHT); + for (size_t dx = 1; dx < len; dx++) putat(y, x + dx, LINE_H); + putat(y, x + len, LINE_T_LEFT); +} + +void vline(uint32_t x, uint32_t y, uint32_t _len) { + uint32_t len = _len - 1; + putat(y, x, LINE_T_DOWN); + for (size_t dy = 1; dy < len; dy++) putat(y + dy, x, LINE_V); + putat(y + len, x, LINE_T_UP); +} + +void text(uint32_t x, uint32_t y, char* fmt, ...) { + va_list args; + va_start(args, fmt); + char buf[256]; + vsnprintf(buf, 256, fmt, args); + va_end(args); + + uint32_t len = strlen(buf); + uint32_t basex = x - len / 2; + + size_t i = 0; + while (buf[i] != '\0') putat(y, basex + i, buf[i++]); +} + diff --git a/boot/stage2/menu.h b/boot/stage2/menu.h new file mode 100644 index 0000000..b85b961 --- /dev/null +++ b/boot/stage2/menu.h @@ -0,0 +1,33 @@ +#ifndef _MENU_H +#define _MENU_H + +// Box drawing characters +#define SHADE_LIGHT 0xB0 +#define SHADE_MEDIUM 0xB1 +#define SHADE_DARK 0xB2 +#define LINE_V 0xB3 +#define LINE_T_LEFT 0xB4 +#define CORNER_TR 0xBF +#define CORNER_BL 0xC0 +#define LINE_T_UP 0xC1 +#define LINE_T_DOWN 0xC2 +#define LINE_T_RIGHT 0xC3 +#define LINE_H 0xC4 +#define LINE_CROSS 0xC5 +#define CORNER_BR 0xD9 +#define CORNER_TL 0xDA +#define BLOCK 0xDB +#define BLOCK_UPPER 0xDC +#define BLOCK_LEFT 0xDD +#define BLOCK_RIGHT 0xDE +#define BLOCK_LOWER 0xDF +#define INT_UPPER 0xF4 +#define INT_LOWER 0xF5 + +void rect(uint32_t x, uint32_t y, uint32_t w, uint32_t h); +void fill(uint32_t x, uint32_t y, uint32_t w, uint32_t h, char c); +void hline(uint32_t x, uint32_t y, uint32_t len); +void vline(uint32_t x, uint32_t y, uint32_t len); +void text(uint32_t x, uint32_t y, char* fmt, ...); + +#endif diff --git a/boot/stage2/port.h b/boot/stage2/port.h new file mode 100644 index 0000000..789fe07 --- /dev/null +++ b/boot/stage2/port.h @@ -0,0 +1,33 @@ +#ifndef PORT_H +#define PORT_H + +#include "stdint.h" + +inline uint8_t inb(uint16_t port) { + uint8_t result; + __asm__ volatile("inb %1, %0" : "=a"(result) : "Nd"(port)); + return result; +} +inline void outb(uint16_t port, uint8_t data) { + __asm__ volatile("outb %0, %1" :: "a"(data), "Nd"(port)); +} + +inline uint16_t inw(uint16_t port) { + uint16_t result; + __asm__ volatile("inw %1, %0" : "=a"(result) : "Nd"(port)); + return result; +} +inline void outw(uint16_t port, uint16_t data) { + __asm__ volatile("outw %0, %1" :: "a"(data), "Nd"(port)); +} + +inline uint32_t inl(uint16_t port) { + uint32_t result; + __asm__ volatile("inl %1, %0" : "=a"(result) : "Nd"(port)); + return result; +} +inline void outl(uint16_t port, uint32_t data) { + __asm__ volatile("outl %0, %1" :: "a"(data), "Nd"(port)); +} + +#endif diff --git a/boot/stage2/stdarg.h b/boot/stage2/stdarg.h new file mode 100644 index 0000000..4d1e8ac --- /dev/null +++ b/boot/stage2/stdarg.h @@ -0,0 +1,10 @@ +#ifndef _STDARG_H +#define _STDARG_H + +typedef char* va_list; +#define va_start(ap, paramn) (void)((ap) = (char*)(&(paramn) + 1)) +#define va_end(ap) (void)((ap) = 0) +#define va_arg(ap, type) (((type*)((ap) = ((ap) + sizeof(type))))[-1]) + +#endif + diff --git a/boot/stage2/stdint.h b/boot/stage2/stdint.h new file mode 100644 index 0000000..cb6d964 --- /dev/null +++ b/boot/stage2/stdint.h @@ -0,0 +1,22 @@ +#ifndef _STDINT_H +#define _STDINT_H + +#define NULL ((void*)0) + +// Naitive size +typedef unsigned int size_t; +typedef signed int ssize_t; + +// Signed ints +typedef signed char int8_t; +typedef signed short int16_t; +typedef signed int int32_t; +typedef signed long long int64_t; + +// Unsigned ints +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long long uint64_t; + +#endif diff --git a/boot/stage2/stdio.c b/boot/stage2/stdio.c new file mode 100644 index 0000000..3b75ee6 --- /dev/null +++ b/boot/stage2/stdio.c @@ -0,0 +1,141 @@ +#include "stdarg.h" +#include "stdint.h" +#include "string.h" +#include "stdio.h" +#include "port.h" + +static uint32_t xpos; +static uint32_t ypos; +static uint8_t attr; + +void setAttr(uint8_t newattr) { + attr = newattr; +} + +void setCursor(uint32_t row, uint32_t col) { + xpos = col; + ypos = row; + updateCursor(); +} + +void updateCursor() { + uint16_t pos = xpos + ypos * COLS; + + outb(0x3d4, 0x0f); + outb(0x3d5, pos & 0xff); + outb(0x3d4, 0x0e); + outb(0x3d5, (pos >> 8) & 0xff); +} + +void hideCursor() { + outb(0x3d4, 0x0a); + outb(0x3d5, 0x20); +} + +void showCursor() { + uint8_t start = 0; + uint8_t end = 15; + + outb(0x3d4, 0x0a); + outb(0x3d5, (inb(0x3d5) & 0xc0) | start); + outb(0x3d4, 0x0b); + outb(0x3d5, (inb(0x3d5) & 0xe0) | end); +} + +void cls() { + uint8_t* vidmem = (uint8_t*)VIDMEM; + + for (size_t i = 0; i < ROWS * COLS; i++) { + vidmem[i * 2] = 0; + vidmem[i * 2 + 1] = attr; + } + + xpos = 0; + ypos = 0; + updateCursor(); +} + +void putat(uint32_t row, uint32_t col, int c) { + uint8_t* vidmem = (uint8_t*)VIDMEM; + vidmem[(col + row * COLS) * 2] = c & 0xFF; + vidmem[(col + row * COLS) * 2 + 1] = attr; +} + +void newline() { + xpos = 0; + ypos++; + if (ypos >= ROWS) ypos = 0; + updateCursor(); +} + +void putc(int c) { + putat(ypos, xpos, c); + xpos++; + if (xpos >= COLS) newline(); + updateCursor(); +} + +void puts(char* s) { + while (*s != '\0') { + if (*s == '\n' || *s == '\r') { + newline(); + s++; + } else putc(*s++); + } +} + +int vsnprintf(void* buf, size_t len, char* fmt, va_list args) { + char* str = (char*)buf; + size_t pos = 0; + + while (*fmt != '\0') { + if (*fmt != '%') { + if (pos < len - 1) str[pos++] = *fmt++; + continue; + } + + fmt++; + char pad = ' '; + int width = 0; + + // TODO: padding + if (*fmt == '0') pad = '0'; + while (*fmt >= '0' && *fmt <= '9') { + width *= 10; + width += *fmt++ - '0'; + } + + // DO NOT TALK ABOUT THIS ABOMINATION + char* s; + switch (*fmt++) { + case 'd': s = itoa(va_arg(args, int), 10); goto string; + case 'x': s = itoa(va_arg(args, int), 16); goto string; + case 's': s = va_arg(args, char*); + string: while (*s != '\0' && pos < len - 1) str[pos++] = *s++; break; + case 'c': if (pos < len - 1) str[pos++] = va_arg(args, char); break; + case '%': if (pos < len - 1) str[pos++] = '%'; break; + default: + if (pos < len - 1) str[pos++] = '%'; + if (pos < len - 1) str[pos++] = *(fmt - 1); + break; + } + } + + if (len > 0) { + if (pos < len) str[pos++] = '\0'; + else str[len - 1] = '\0'; // Shouldn't be able to be reached, but who knows + } + + return pos; +} + +int printf(char* fmt, ...) { + va_list args; + va_start(args, fmt); + char buf[256]; + int ret = vsnprintf(buf, 256, fmt, args); + va_end(args); + puts(buf); + return ret; +} + diff --git a/boot/stage2/stdio.h b/boot/stage2/stdio.h new file mode 100644 index 0000000..9ce4b05 --- /dev/null +++ b/boot/stage2/stdio.h @@ -0,0 +1,25 @@ +#ifndef _STDIO_H +#define _STDIO_H + +#include "stdarg.h" +#include "stdint.h" + +#define VIDMEM 0xb8000 +#define COLS 80 +#define ROWS 25 + +void setAttr(uint8_t attr); +void setCursor(uint32_t row, uint32_t col); +void updateCursor(); +void hideCursor(); +void showCursor(); + +void cls(); +void newline(); +void putc(int c); +void puts(char* s); +int printf(char* fmt, ...); +int vsnprintf(void* buf, size_t len, char* fmt, va_list args); +void putat(uint32_t row, uint32_t col, int c); + +#endif diff --git a/boot/stage2/string.c b/boot/stage2/string.c new file mode 100644 index 0000000..3d67650 --- /dev/null +++ b/boot/stage2/string.c @@ -0,0 +1,74 @@ +#include "stdint.h" +#include "string.h" + +char* itoa(size_t val, int base) { + static char buf[32] = { 0 }; + + if (base == 0 || base > 16) return NULL; + + if (val == 0) { + buf[0] = '0'; + buf[1] = '\0'; + return buf; + } + + int i; + buf[31] = '\0'; + for (i = 30; val && i; i--, val /= base) { + buf[i] = "0123456789abcdef"[val % base]; + } + + return &buf[i + 1]; +} + +void* memcpy(void* src, void* dst, size_t length) { + uint8_t* p = dst; + size_t i = 0; + while (i < length) p[i] = *(uint8_t*)(src + i); + return dst; +} + +void* memset(void* dst, uint8_t val, size_t length) { + uint8_t* p = dst; + size_t i = 0; + while (i < length) p[i++] = val; + return dst; +} + +char* strcpy(char* str1, const char* str2) { + char* p = str1; + while (*str2 != '\0') *p++ = *str2++; + return str1; +} + +char* strcat(char* str1, const char* str2) { + char* p = str1; + while (*str2++ != '\0'); + while (*str2 != '\0') *p++ = *str2++; + return str1; +} + +char* strchr(const char* str, char c) { + char* p = (char*)str; + while (*p != '\0' && *p != c) p++; + return (*p == c) ? p : NULL; +} + +int strcmp(const char* str1, const char* str2) { + while (*str1 != '\0' && *str1 == *str2) { + str1++; + str2++; + } + + uint8_t c1 = (*(uint8_t*)str1); + uint8_t c2 = (*(uint8_t*)str2); + + return ((c1 < c2) ? -1 : (c1 > c2)); +} + +size_t strlen(const char* str) { + size_t len = 0; + while (str[len++] != '\0'); + return len; +} + diff --git a/boot/stage2/string.h b/boot/stage2/string.h new file mode 100644 index 0000000..7f65eaf --- /dev/null +++ b/boot/stage2/string.h @@ -0,0 +1,15 @@ +#ifndef _STRING_H +#define _STRING_H + +#include "stdint.h" + +char* itoa(size_t val, int base); +void* memcpy(void* src, void* dst, size_t length); +void* memset(void* dst, uint8_t value, size_t length); +char* strcpy(char* str1, const char* str2); +char* strcat(char* str1, const char* str2); +char* strchr(const char* str, char c); +int strcmp(const char* str1, const char* str2); +size_t strlen(const char* str); + +#endif diff --git a/defaults.mk b/defaults.mk index 9c85750..d808bbf 100644 --- a/defaults.mk +++ b/defaults.mk @@ -8,7 +8,7 @@ OBJCOPY = i686-elf-objcopy MAKE = make # Flags -HOSTCFLAGS = -Wall -Wextra -Wpedantic -O2 -std=c17 -g +HOSTCFLAGS = -Wall -Wextra -Wpedantic -Os -std=c17 -g CFLAGS = -Wall -Wextra -Wpedantic -Wno-pointer-arith\ -ffreestanding -fno-stack-protector -fno-builtin -fno-pie -fcommon\ -O2 -std=c17 -nostdinc -nostdlib -z notext -march=i386 -g diff --git a/docs/coding-style.txt b/docs/coding-style.txt index e51e283..56a5a98 100644 --- a/docs/coding-style.txt +++ b/docs/coding-style.txt @@ -196,3 +196,19 @@ The prefered way of ordering '#include' directives is as so: Directives should be ordered by lenght, descending. If two or more includes have the same length, order alphabetically. +Header Guards +************* +`#ifndef X #define X` header guards are preffered. To avoid conflicts they +should follow this format: +`#define _PATH_TO_HEADER_H` + +For example `drivers/fat32.h would have this guard: +``` +#ifndef _DRIVERS_FAT32_H +#define _DRIVERS_FAT32_H + +/* Header stuff */ + +#endif +``` + diff --git a/libc/string/itoa.c b/libc/string/itoa.c index 478e5e1..55c8098 100644 --- a/libc/string/itoa.c +++ b/libc/string/itoa.c @@ -8,6 +8,7 @@ char* itoa(size_t val, int base) { if (val == 0) { buf[0] = '0'; + buf[1] = '\0'; return buf; } diff --git a/makefile b/makefile index 7966e1b..1832629 100644 --- a/makefile +++ b/makefile @@ -29,7 +29,7 @@ clean: qemu: qemu-system-x86_64\ -drive format=raw,file=$(IMG),index=0,media=disk\ - -m 256M -accel tcg -monitor stdio\ + -m 256M -accel tcg -monitor stdio -net none\ -rtc base=localtime,clock=host,driftfix=slew\ -audiodev coreaudio,id=audio0 -machine pcspk-audiodev=audio0