mirror of
				https://github.com/cfenollosa/os-tutorial.git
				synced 2025-06-13 12:54:24 +00:00 
			
		
		
		
	lesson 23, step 3
This commit is contained in:
		
							parent
							
								
									92ff191c3d
								
							
						
					
					
						commit
						de3d442569
					
				@ -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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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));
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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) {
 | 
			
		||||
 | 
			
		||||
@ -1,3 +1 @@
 | 
			
		||||
#include "../cpu/type.h"
 | 
			
		||||
 | 
			
		||||
void init_keyboard();
 | 
			
		||||
 | 
			
		||||
@ -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] = ' ';
 | 
			
		||||
 | 
			
		||||
@ -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,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] = "";
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user