Carlos преди 9 години
родител
ревизия
de3d442569

+ 11 - 7
23-fixes/README.md

@@ -16,13 +16,9 @@ We add  `-ffreestanding` when compiling `.o` files, which includes `kernel_entry
 Before, we disabled libgcc (not libc) through the use of `-nostdlib` and we didn't re-enable
 it for linking. Since this is tricky, we'll delete `-nostdlib`
 
+`-nostdinc` was also pased to gcc, but we will need it for step 3.
 
-2. Not setting a stack
-----------------------
-
-
-
-3. kernel.c `main()` function
+2. kernel.c `main()` function
 -----------------------------
 
 Modify `kernel/kernel.c` and change `main()` to `kernel_main()` since gcc recognizes "main" as 
@@ -33,8 +29,16 @@ Change `boot/kernel_entry.asm` to point to the new name accordingly.
 To fix the `i386-elf-ld: warning: cannot find entry symbol _start; defaulting to 0000000000001000`
 warning message, add a `global _start;` and define the `_start:` label in `boot/kernel_entry.asm`.
 
-4. Reinvented datatypes
+
+3. Reinvented datatypes
 -----------------------
+
+It looks like it was a bad idea to define non-standard data types like `u32` and such, since
+C99 introduces standard fixed-width data types like `uint32_t`
+
+We need to include `<stdint.h>` which works even in `-ffreestanding` (but requires stdlibs)
+and use those data types instead of our own, then delete them on `type.h`
+
 <stddef.h> to provide size\_t
 
 

+ 3 - 2
23-fixes/cpu/idt.c

@@ -1,6 +1,7 @@
 #include "idt.h"
+#include "type.h"
 
-void set_idt_gate(int n, u32 handler) {
+void set_idt_gate(int n, uint32_t handler) {
     idt[n].low_offset = low_16(handler);
     idt[n].sel = KERNEL_CS;
     idt[n].always0 = 0;
@@ -9,7 +10,7 @@ void set_idt_gate(int n, u32 handler) {
 }
 
 void set_idt() {
-    idt_reg.base = (u32) &idt;
+    idt_reg.base = (uint32_t) &idt;
     idt_reg.limit = IDT_ENTRIES * sizeof(idt_gate_t) - 1;
     /* Don't make the mistake of loading &idt -- always load &idt_reg */
     __asm__ __volatile__("lidtl (%0)" : : "r" (&idt_reg));

+ 9 - 9
23-fixes/cpu/idt.h

@@ -1,30 +1,30 @@
 #ifndef IDT_H
 #define IDT_H
 
-#include "type.h"
+#include <stdint.h>
 
 /* Segment selectors */
 #define KERNEL_CS 0x08
 
 /* How every interrupt gate (handler) is defined */
 typedef struct {
-    u16 low_offset; /* Lower 16 bits of handler function address */
-    u16 sel; /* Kernel segment selector */
-    u8 always0;
+    uint16_t low_offset; /* Lower 16 bits of handler function address */
+    uint16_t sel; /* Kernel segment selector */
+    uint8_t always0;
     /* First byte
      * Bit 7: "Interrupt is present"
      * Bits 6-5: Privilege level of caller (0=kernel..3=user)
      * Bit 4: Set to 0 for interrupt gates
      * Bits 3-0: bits 1110 = decimal 14 = "32 bit interrupt gate" */
-    u8 flags; 
-    u16 high_offset; /* Higher 16 bits of handler function address */
+    uint8_t flags; 
+    uint16_t high_offset; /* Higher 16 bits of handler function address */
 } __attribute__((packed)) idt_gate_t ;
 
 /* A pointer to the array of interrupt handlers.
  * Assembly instruction 'lidt' will read it */
 typedef struct {
-    u16 limit;
-    u32 base;
+    uint16_t limit;
+    uint32_t base;
 } __attribute__((packed)) idt_register_t;
 
 #define IDT_ENTRIES 256
@@ -33,7 +33,7 @@ idt_register_t idt_reg;
 
 
 /* Functions implemented in idt.c */
-void set_idt_gate(int n, u32 handler);
+void set_idt_gate(int n, uint32_t handler);
 void set_idt();
 
 #endif

+ 49 - 49
23-fixes/cpu/isr.c

@@ -11,38 +11,38 @@ isr_t interrupt_handlers[256];
 /* Can't do this with a loop because we need the address
  * of the function names */
 void isr_install() {
-    set_idt_gate(0, (u32)isr0);
-    set_idt_gate(1, (u32)isr1);
-    set_idt_gate(2, (u32)isr2);
-    set_idt_gate(3, (u32)isr3);
-    set_idt_gate(4, (u32)isr4);
-    set_idt_gate(5, (u32)isr5);
-    set_idt_gate(6, (u32)isr6);
-    set_idt_gate(7, (u32)isr7);
-    set_idt_gate(8, (u32)isr8);
-    set_idt_gate(9, (u32)isr9);
-    set_idt_gate(10, (u32)isr10);
-    set_idt_gate(11, (u32)isr11);
-    set_idt_gate(12, (u32)isr12);
-    set_idt_gate(13, (u32)isr13);
-    set_idt_gate(14, (u32)isr14);
-    set_idt_gate(15, (u32)isr15);
-    set_idt_gate(16, (u32)isr16);
-    set_idt_gate(17, (u32)isr17);
-    set_idt_gate(18, (u32)isr18);
-    set_idt_gate(19, (u32)isr19);
-    set_idt_gate(20, (u32)isr20);
-    set_idt_gate(21, (u32)isr21);
-    set_idt_gate(22, (u32)isr22);
-    set_idt_gate(23, (u32)isr23);
-    set_idt_gate(24, (u32)isr24);
-    set_idt_gate(25, (u32)isr25);
-    set_idt_gate(26, (u32)isr26);
-    set_idt_gate(27, (u32)isr27);
-    set_idt_gate(28, (u32)isr28);
-    set_idt_gate(29, (u32)isr29);
-    set_idt_gate(30, (u32)isr30);
-    set_idt_gate(31, (u32)isr31);
+    set_idt_gate(0, (uint32_t)isr0);
+    set_idt_gate(1, (uint32_t)isr1);
+    set_idt_gate(2, (uint32_t)isr2);
+    set_idt_gate(3, (uint32_t)isr3);
+    set_idt_gate(4, (uint32_t)isr4);
+    set_idt_gate(5, (uint32_t)isr5);
+    set_idt_gate(6, (uint32_t)isr6);
+    set_idt_gate(7, (uint32_t)isr7);
+    set_idt_gate(8, (uint32_t)isr8);
+    set_idt_gate(9, (uint32_t)isr9);
+    set_idt_gate(10, (uint32_t)isr10);
+    set_idt_gate(11, (uint32_t)isr11);
+    set_idt_gate(12, (uint32_t)isr12);
+    set_idt_gate(13, (uint32_t)isr13);
+    set_idt_gate(14, (uint32_t)isr14);
+    set_idt_gate(15, (uint32_t)isr15);
+    set_idt_gate(16, (uint32_t)isr16);
+    set_idt_gate(17, (uint32_t)isr17);
+    set_idt_gate(18, (uint32_t)isr18);
+    set_idt_gate(19, (uint32_t)isr19);
+    set_idt_gate(20, (uint32_t)isr20);
+    set_idt_gate(21, (uint32_t)isr21);
+    set_idt_gate(22, (uint32_t)isr22);
+    set_idt_gate(23, (uint32_t)isr23);
+    set_idt_gate(24, (uint32_t)isr24);
+    set_idt_gate(25, (uint32_t)isr25);
+    set_idt_gate(26, (uint32_t)isr26);
+    set_idt_gate(27, (uint32_t)isr27);
+    set_idt_gate(28, (uint32_t)isr28);
+    set_idt_gate(29, (uint32_t)isr29);
+    set_idt_gate(30, (uint32_t)isr30);
+    set_idt_gate(31, (uint32_t)isr31);
 
     // Remap the PIC
     port_byte_out(0x20, 0x11);
@@ -57,22 +57,22 @@ void isr_install() {
     port_byte_out(0xA1, 0x0); 
 
     // Install the IRQs
-    set_idt_gate(32, (u32)irq0);
-    set_idt_gate(33, (u32)irq1);
-    set_idt_gate(34, (u32)irq2);
-    set_idt_gate(35, (u32)irq3);
-    set_idt_gate(36, (u32)irq4);
-    set_idt_gate(37, (u32)irq5);
-    set_idt_gate(38, (u32)irq6);
-    set_idt_gate(39, (u32)irq7);
-    set_idt_gate(40, (u32)irq8);
-    set_idt_gate(41, (u32)irq9);
-    set_idt_gate(42, (u32)irq10);
-    set_idt_gate(43, (u32)irq11);
-    set_idt_gate(44, (u32)irq12);
-    set_idt_gate(45, (u32)irq13);
-    set_idt_gate(46, (u32)irq14);
-    set_idt_gate(47, (u32)irq15);
+    set_idt_gate(32, (uint32_t)irq0);
+    set_idt_gate(33, (uint32_t)irq1);
+    set_idt_gate(34, (uint32_t)irq2);
+    set_idt_gate(35, (uint32_t)irq3);
+    set_idt_gate(36, (uint32_t)irq4);
+    set_idt_gate(37, (uint32_t)irq5);
+    set_idt_gate(38, (uint32_t)irq6);
+    set_idt_gate(39, (uint32_t)irq7);
+    set_idt_gate(40, (uint32_t)irq8);
+    set_idt_gate(41, (uint32_t)irq9);
+    set_idt_gate(42, (uint32_t)irq10);
+    set_idt_gate(43, (uint32_t)irq11);
+    set_idt_gate(44, (uint32_t)irq12);
+    set_idt_gate(45, (uint32_t)irq13);
+    set_idt_gate(46, (uint32_t)irq14);
+    set_idt_gate(47, (uint32_t)irq15);
 
     set_idt(); // Load with ASM
 }
@@ -126,7 +126,7 @@ void isr_handler(registers_t r) {
     kprint("\n");
 }
 
-void register_interrupt_handler(u8 n, isr_t handler) {
+void register_interrupt_handler(uint8_t n, isr_t handler) {
     interrupt_handlers[n] = handler;
 }
 

+ 6 - 6
23-fixes/cpu/isr.h

@@ -1,7 +1,7 @@
 #ifndef ISR_H
 #define ISR_H
 
-#include "type.h"
+#include <stdint.h>
 
 /* ISRs reserved for CPU exceptions */
 extern void isr0();
@@ -73,10 +73,10 @@ extern void irq15();
 
 /* Struct which aggregates many registers */
 typedef struct {
-   u32 ds; /* Data segment selector */
-   u32 edi, esi, ebp, esp, ebx, edx, ecx, eax; /* Pushed by pusha. */
-   u32 int_no, err_code; /* Interrupt number and error code (if applicable) */
-   u32 eip, cs, eflags, useresp, ss; /* Pushed by the processor automatically */
+   uint32_t ds; /* Data segment selector */
+   uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; /* Pushed by pusha. */
+   uint32_t int_no, err_code; /* Interrupt number and error code (if applicable) */
+   uint32_t eip, cs, eflags, useresp, ss; /* Pushed by the processor automatically */
 } registers_t;
 
 void isr_install();
@@ -84,6 +84,6 @@ void isr_handler(registers_t r);
 void irq_install();
 
 typedef void (*isr_t)(registers_t);
-void register_interrupt_handler(u8 n, isr_t handler);
+void register_interrupt_handler(uint8_t n, isr_t handler);
 
 #endif

+ 6 - 6
23-fixes/cpu/ports.c

@@ -3,8 +3,8 @@
 /**
  * Read a byte from the specified port
  */
-u8 port_byte_in (u16 port) {
-    u8 result;
+uint8_t port_byte_in (uint16_t port) {
+    uint8_t result;
     /* Inline assembler syntax
      * !! Notice how the source and destination registers are switched from NASM !!
      *
@@ -17,7 +17,7 @@ u8 port_byte_in (u16 port) {
     return result;
 }
 
-void port_byte_out (u16 port, u8 data) {
+void port_byte_out (uint16_t port, uint8_t data) {
     /* Notice how here both registers are mapped to C variables and
      * nothing is returned, thus, no equals '=' in the asm syntax 
      * However we see a comma since there are two variables in the input area
@@ -26,12 +26,12 @@ void port_byte_out (u16 port, u8 data) {
     __asm__ __volatile__("out %%al, %%dx" : : "a" (data), "d" (port));
 }
 
-u16 port_word_in (u16 port) {
-    u16 result;
+uint16_t port_word_in (uint16_t port) {
+    uint16_t result;
     __asm__("in %%dx, %%ax" : "=a" (result) : "d" (port));
     return result;
 }
 
-void port_word_out (u16 port, u16 data) {
+void port_word_out (uint16_t port, uint16_t data) {
     __asm__ __volatile__("out %%ax, %%dx" : : "a" (data), "d" (port));
 }

+ 5 - 5
23-fixes/cpu/ports.h

@@ -1,11 +1,11 @@
 #ifndef PORTS_H
 #define PORTS_H
 
-#include "../cpu/type.h"
+#include <stdint.h>
 
-unsigned char port_byte_in (u16 port);
-void port_byte_out (u16 port, u8 data);
-unsigned short port_word_in (u16 port);
-void port_word_out (u16 port, u16 data);
+unsigned char port_byte_in (uint16_t port);
+void port_byte_out (uint16_t port, uint8_t data);
+unsigned short port_word_in (uint16_t port);
+void port_word_out (uint16_t port, uint16_t data);
 
 #endif

+ 5 - 5
23-fixes/cpu/timer.c

@@ -3,21 +3,21 @@
 #include "ports.h"
 #include "../libc/function.h"
 
-u32 tick = 0;
+uint32_t tick = 0;
 
 static void timer_callback(registers_t regs) {
     tick++;
     UNUSED(regs);
 }
 
-void init_timer(u32 freq) {
+void init_timer(uint32_t freq) {
     /* Install the function we just wrote */
     register_interrupt_handler(IRQ0, timer_callback);
 
     /* Get the PIT value: hardware clock at 1193180 Hz */
-    u32 divisor = 1193180 / freq;
-    u8 low  = (u8)(divisor & 0xFF);
-    u8 high = (u8)( (divisor >> 8) & 0xFF);
+    uint32_t divisor = 1193180 / freq;
+    uint8_t low  = (uint8_t)(divisor & 0xFF);
+    uint8_t high = (uint8_t)( (divisor >> 8) & 0xFF);
     /* Send the command */
     port_byte_out(0x43, 0x36); /* Command port */
     port_byte_out(0x40, low);

+ 2 - 2
23-fixes/cpu/timer.h

@@ -1,8 +1,8 @@
 #ifndef TIMER_H
 #define TIMER_H
 
-#include "type.h"
+#include <stdint.h>
 
-void init_timer(u32 freq);
+void init_timer(uint32_t freq);
 
 #endif

+ 3 - 10
23-fixes/cpu/type.h

@@ -1,16 +1,9 @@
 #ifndef TYPE_H
 #define TYPE_H
 
-/* Instead of using 'chars' to allocate non-character bytes,
- * we will use these new type with no semantic meaning */
-typedef unsigned int   u32;
-typedef          int   s32;
-typedef unsigned short u16;
-typedef          short s16;
-typedef unsigned char  u8;
-typedef          char  s8;
+#include <stdint.h>
 
-#define low_16(address) (u16)((address) & 0xFFFF)
-#define high_16(address) (u16)(((address) >> 16) & 0xFFFF)
+#define low_16(address) (uint16_t)((address) & 0xFFFF)
+#define high_16(address) (uint16_t)(((address) >> 16) & 0xFFFF)
 
 #endif

+ 2 - 1
23-fixes/drivers/keyboard.c

@@ -5,6 +5,7 @@
 #include "../libc/string.h"
 #include "../libc/function.h"
 #include "../kernel/kernel.h"
+#include <stdint.h>
 
 #define BACKSPACE 0x0E
 #define ENTER 0x1C
@@ -26,7 +27,7 @@ const char sc_ascii[] = { '?', '?', '1', '2', '3', '4', '5', '6',
 
 static void keyboard_callback(registers_t regs) {
     /* The PIC leaves us the scancode in port 0x60 */
-    u8 scancode = port_byte_in(0x60);
+    uint8_t scancode = port_byte_in(0x60);
     
     if (scancode > SC_MAX) return;
     if (scancode == BACKSPACE) {

+ 0 - 2
23-fixes/drivers/keyboard.h

@@ -1,3 +1 @@
-#include "../cpu/type.h"
-
 void init_keyboard();

+ 8 - 7
23-fixes/drivers/screen.c

@@ -1,6 +1,7 @@
 #include "screen.h"
 #include "../cpu/ports.h"
 #include "../libc/mem.h"
+#include <stdint.h>
 
 /* Declaration of private functions */
 int get_cursor_offset();
@@ -65,7 +66,7 @@ void kprint_backspace() {
  * Sets the video cursor to the returned offset
  */
 int print_char(char c, int col, int row, char attr) {
-    u8 *vidmem = (u8*) VIDEO_ADDRESS;
+    uint8_t *vidmem = (uint8_t*) VIDEO_ADDRESS;
     if (!attr) attr = WHITE_ON_BLACK;
 
     /* Error control: print a red 'E' if the coords aren't right */
@@ -95,12 +96,12 @@ int print_char(char c, int col, int row, char attr) {
     if (offset >= MAX_ROWS * MAX_COLS * 2) {
         int i;
         for (i = 1; i < MAX_ROWS; i++) 
-            memory_copy((u8*)(get_offset(0, i) + VIDEO_ADDRESS),
-                        (u8*)(get_offset(0, i-1) + VIDEO_ADDRESS),
+            memory_copy((uint8_t*)(get_offset(0, i) + VIDEO_ADDRESS),
+                        (uint8_t*)(get_offset(0, i-1) + VIDEO_ADDRESS),
                         MAX_COLS * 2);
 
         /* Blank last line */
-        char *last_line = (char*) (get_offset(0, MAX_ROWS-1) + (u8*) VIDEO_ADDRESS);
+        char *last_line = (char*) (get_offset(0, MAX_ROWS-1) + (uint8_t*) VIDEO_ADDRESS);
         for (i = 0; i < MAX_COLS * 2; i++) last_line[i] = 0;
 
         offset -= 2 * MAX_COLS;
@@ -126,15 +127,15 @@ void set_cursor_offset(int offset) {
     /* Similar to get_cursor_offset, but instead of reading we write data */
     offset /= 2;
     port_byte_out(REG_SCREEN_CTRL, 14);
-    port_byte_out(REG_SCREEN_DATA, (u8)(offset >> 8));
+    port_byte_out(REG_SCREEN_DATA, (uint8_t)(offset >> 8));
     port_byte_out(REG_SCREEN_CTRL, 15);
-    port_byte_out(REG_SCREEN_DATA, (u8)(offset & 0xff));
+    port_byte_out(REG_SCREEN_DATA, (uint8_t)(offset & 0xff));
 }
 
 void clear_screen() {
     int screen_size = MAX_COLS * MAX_ROWS;
     int i;
-    u8 *screen = (u8*) VIDEO_ADDRESS;
+    uint8_t *screen = (uint8_t*) VIDEO_ADDRESS;
 
     for (i = 0; i < screen_size; i++) {
         screen[i*2] = ' ';

+ 0 - 2
23-fixes/drivers/screen.h

@@ -1,8 +1,6 @@
 #ifndef SCREEN_H
 #define SCREEN_H
 
-#include "../cpu/type.h"
-
 #define VIDEO_ADDRESS 0xb8000
 #define MAX_ROWS 25
 #define MAX_COLS 80

+ 3 - 2
23-fixes/kernel/kernel.c

@@ -3,6 +3,7 @@
 #include "kernel.h"
 #include "../libc/string.h"
 #include "../libc/mem.h"
+#include <stdint.h>
 
 void kernel_main() {
     isr_install();
@@ -18,8 +19,8 @@ void user_input(char *input) {
         asm volatile("hlt");
     } else if (strcmp(input, "PAGE") == 0) {
         /* Lesson 22: Code to test kmalloc, the rest is unchanged */
-        u32 phys_addr;
-        u32 page = kmalloc(1000, 1, &phys_addr);
+        uint32_t phys_addr;
+        uint32_t page = kmalloc(1000, 1, &phys_addr);
         char page_str[16] = "";
         hex_to_ascii(page, page_str);
         char phys_str[16] = "";

+ 6 - 6
23-fixes/libc/mem.c

@@ -1,24 +1,24 @@
 #include "mem.h"
 
-void memory_copy(u8 *source, u8 *dest, int nbytes) {
+void memory_copy(uint8_t *source, uint8_t *dest, int nbytes) {
     int i;
     for (i = 0; i < nbytes; i++) {
         *(dest + i) = *(source + i);
     }
 }
 
-void memory_set(u8 *dest, u8 val, u32 len) {
-    u8 *temp = (u8 *)dest;
+void memory_set(uint8_t *dest, uint8_t val, uint32_t len) {
+    uint8_t *temp = (uint8_t *)dest;
     for ( ; len != 0; len--) *temp++ = val;
 }
 
 /* This should be computed at link time, but a hardcoded
  * value is fine for now. Remember that our kernel starts
  * at 0x1000 as defined on the Makefile */
-u32 free_mem_addr = 0x10000;
+uint32_t free_mem_addr = 0x10000;
 /* Implementation is just a pointer to some free memory which
  * keeps growing */
-u32 kmalloc(u32 size, int align, u32 *phys_addr) {
+uint32_t kmalloc(uint32_t size, int align, uint32_t *phys_addr) {
     /* Pages are aligned to 4K, or 0x1000 */
     if (align == 1 && (free_mem_addr & 0xFFFFF000)) {
         free_mem_addr &= 0xFFFFF000;
@@ -27,7 +27,7 @@ u32 kmalloc(u32 size, int align, u32 *phys_addr) {
     /* Save also the physical address */
     if (phys_addr) *phys_addr = free_mem_addr;
 
-    u32 ret = free_mem_addr;
+    uint32_t ret = free_mem_addr;
     free_mem_addr += size; /* Remember to increment the pointer */
     return ret;
 }

+ 4 - 4
23-fixes/libc/mem.h

@@ -1,12 +1,12 @@
 #ifndef MEM_H
 #define MEM_H
 
-#include "../cpu/type.h"
+#include <stdint.h>
 
-void memory_copy(u8 *source, u8 *dest, int nbytes);
-void memory_set(u8 *dest, u8 val, u32 len);
+void memory_copy(uint8_t *source, uint8_t *dest, int nbytes);
+void memory_set(uint8_t *dest, uint8_t val, uint32_t len);
 
 /* At this stage there is no 'free' implemented. */
-u32 kmalloc(u32 size, int align, u32 *phys_addr);
+uint32_t kmalloc(uint32_t size, int align, uint32_t *phys_addr);
 
 #endif

+ 2 - 2
23-fixes/libc/string.c

@@ -1,5 +1,5 @@
 #include "string.h"
-#include "../cpu/type.h"
+#include <stdint.h>
 
 /**
  * K&R implementation
@@ -23,7 +23,7 @@ void hex_to_ascii(int n, char str[]) {
     append(str, 'x');
     char zeros = 0;
 
-    s32 tmp;
+    int32_t tmp;
     int i;
     for (i = 28; i > 0; i -= 4) {
         tmp = (n >> i) & 0xF;