mirror of
https://github.com/cfenollosa/os-tutorial.git
synced 2024-10-27 20:34:19 +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
|
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`
|
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
|
2. kernel.c `main()` function
|
||||||
----------------------
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
3. kernel.c `main()` function
|
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
|
||||||
Modify `kernel/kernel.c` and change `main()` to `kernel_main()` since gcc recognizes "main" as
|
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`
|
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`.
|
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
|
<stddef.h> to provide size\_t
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "idt.h"
|
#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].low_offset = low_16(handler);
|
||||||
idt[n].sel = KERNEL_CS;
|
idt[n].sel = KERNEL_CS;
|
||||||
idt[n].always0 = 0;
|
idt[n].always0 = 0;
|
||||||
@ -9,7 +10,7 @@ void set_idt_gate(int n, u32 handler) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void set_idt() {
|
void set_idt() {
|
||||||
idt_reg.base = (u32) &idt;
|
idt_reg.base = (uint32_t) &idt;
|
||||||
idt_reg.limit = IDT_ENTRIES * sizeof(idt_gate_t) - 1;
|
idt_reg.limit = IDT_ENTRIES * sizeof(idt_gate_t) - 1;
|
||||||
/* Don't make the mistake of loading &idt -- always load &idt_reg */
|
/* Don't make the mistake of loading &idt -- always load &idt_reg */
|
||||||
__asm__ __volatile__("lidtl (%0)" : : "r" (&idt_reg));
|
__asm__ __volatile__("lidtl (%0)" : : "r" (&idt_reg));
|
||||||
|
@ -1,30 +1,30 @@
|
|||||||
#ifndef IDT_H
|
#ifndef IDT_H
|
||||||
#define IDT_H
|
#define IDT_H
|
||||||
|
|
||||||
#include "type.h"
|
#include <stdint.h>
|
||||||
|
|
||||||
/* Segment selectors */
|
/* Segment selectors */
|
||||||
#define KERNEL_CS 0x08
|
#define KERNEL_CS 0x08
|
||||||
|
|
||||||
/* How every interrupt gate (handler) is defined */
|
/* How every interrupt gate (handler) is defined */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u16 low_offset; /* Lower 16 bits of handler function address */
|
uint16_t low_offset; /* Lower 16 bits of handler function address */
|
||||||
u16 sel; /* Kernel segment selector */
|
uint16_t sel; /* Kernel segment selector */
|
||||||
u8 always0;
|
uint8_t always0;
|
||||||
/* First byte
|
/* First byte
|
||||||
* Bit 7: "Interrupt is present"
|
* Bit 7: "Interrupt is present"
|
||||||
* Bits 6-5: Privilege level of caller (0=kernel..3=user)
|
* Bits 6-5: Privilege level of caller (0=kernel..3=user)
|
||||||
* Bit 4: Set to 0 for interrupt gates
|
* Bit 4: Set to 0 for interrupt gates
|
||||||
* Bits 3-0: bits 1110 = decimal 14 = "32 bit interrupt gate" */
|
* Bits 3-0: bits 1110 = decimal 14 = "32 bit interrupt gate" */
|
||||||
u8 flags;
|
uint8_t flags;
|
||||||
u16 high_offset; /* Higher 16 bits of handler function address */
|
uint16_t high_offset; /* Higher 16 bits of handler function address */
|
||||||
} __attribute__((packed)) idt_gate_t ;
|
} __attribute__((packed)) idt_gate_t ;
|
||||||
|
|
||||||
/* A pointer to the array of interrupt handlers.
|
/* A pointer to the array of interrupt handlers.
|
||||||
* Assembly instruction 'lidt' will read it */
|
* Assembly instruction 'lidt' will read it */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u16 limit;
|
uint16_t limit;
|
||||||
u32 base;
|
uint32_t base;
|
||||||
} __attribute__((packed)) idt_register_t;
|
} __attribute__((packed)) idt_register_t;
|
||||||
|
|
||||||
#define IDT_ENTRIES 256
|
#define IDT_ENTRIES 256
|
||||||
@ -33,7 +33,7 @@ idt_register_t idt_reg;
|
|||||||
|
|
||||||
|
|
||||||
/* Functions implemented in idt.c */
|
/* 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();
|
void set_idt();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -11,38 +11,38 @@ isr_t interrupt_handlers[256];
|
|||||||
/* Can't do this with a loop because we need the address
|
/* Can't do this with a loop because we need the address
|
||||||
* of the function names */
|
* of the function names */
|
||||||
void isr_install() {
|
void isr_install() {
|
||||||
set_idt_gate(0, (u32)isr0);
|
set_idt_gate(0, (uint32_t)isr0);
|
||||||
set_idt_gate(1, (u32)isr1);
|
set_idt_gate(1, (uint32_t)isr1);
|
||||||
set_idt_gate(2, (u32)isr2);
|
set_idt_gate(2, (uint32_t)isr2);
|
||||||
set_idt_gate(3, (u32)isr3);
|
set_idt_gate(3, (uint32_t)isr3);
|
||||||
set_idt_gate(4, (u32)isr4);
|
set_idt_gate(4, (uint32_t)isr4);
|
||||||
set_idt_gate(5, (u32)isr5);
|
set_idt_gate(5, (uint32_t)isr5);
|
||||||
set_idt_gate(6, (u32)isr6);
|
set_idt_gate(6, (uint32_t)isr6);
|
||||||
set_idt_gate(7, (u32)isr7);
|
set_idt_gate(7, (uint32_t)isr7);
|
||||||
set_idt_gate(8, (u32)isr8);
|
set_idt_gate(8, (uint32_t)isr8);
|
||||||
set_idt_gate(9, (u32)isr9);
|
set_idt_gate(9, (uint32_t)isr9);
|
||||||
set_idt_gate(10, (u32)isr10);
|
set_idt_gate(10, (uint32_t)isr10);
|
||||||
set_idt_gate(11, (u32)isr11);
|
set_idt_gate(11, (uint32_t)isr11);
|
||||||
set_idt_gate(12, (u32)isr12);
|
set_idt_gate(12, (uint32_t)isr12);
|
||||||
set_idt_gate(13, (u32)isr13);
|
set_idt_gate(13, (uint32_t)isr13);
|
||||||
set_idt_gate(14, (u32)isr14);
|
set_idt_gate(14, (uint32_t)isr14);
|
||||||
set_idt_gate(15, (u32)isr15);
|
set_idt_gate(15, (uint32_t)isr15);
|
||||||
set_idt_gate(16, (u32)isr16);
|
set_idt_gate(16, (uint32_t)isr16);
|
||||||
set_idt_gate(17, (u32)isr17);
|
set_idt_gate(17, (uint32_t)isr17);
|
||||||
set_idt_gate(18, (u32)isr18);
|
set_idt_gate(18, (uint32_t)isr18);
|
||||||
set_idt_gate(19, (u32)isr19);
|
set_idt_gate(19, (uint32_t)isr19);
|
||||||
set_idt_gate(20, (u32)isr20);
|
set_idt_gate(20, (uint32_t)isr20);
|
||||||
set_idt_gate(21, (u32)isr21);
|
set_idt_gate(21, (uint32_t)isr21);
|
||||||
set_idt_gate(22, (u32)isr22);
|
set_idt_gate(22, (uint32_t)isr22);
|
||||||
set_idt_gate(23, (u32)isr23);
|
set_idt_gate(23, (uint32_t)isr23);
|
||||||
set_idt_gate(24, (u32)isr24);
|
set_idt_gate(24, (uint32_t)isr24);
|
||||||
set_idt_gate(25, (u32)isr25);
|
set_idt_gate(25, (uint32_t)isr25);
|
||||||
set_idt_gate(26, (u32)isr26);
|
set_idt_gate(26, (uint32_t)isr26);
|
||||||
set_idt_gate(27, (u32)isr27);
|
set_idt_gate(27, (uint32_t)isr27);
|
||||||
set_idt_gate(28, (u32)isr28);
|
set_idt_gate(28, (uint32_t)isr28);
|
||||||
set_idt_gate(29, (u32)isr29);
|
set_idt_gate(29, (uint32_t)isr29);
|
||||||
set_idt_gate(30, (u32)isr30);
|
set_idt_gate(30, (uint32_t)isr30);
|
||||||
set_idt_gate(31, (u32)isr31);
|
set_idt_gate(31, (uint32_t)isr31);
|
||||||
|
|
||||||
// Remap the PIC
|
// Remap the PIC
|
||||||
port_byte_out(0x20, 0x11);
|
port_byte_out(0x20, 0x11);
|
||||||
@ -57,22 +57,22 @@ void isr_install() {
|
|||||||
port_byte_out(0xA1, 0x0);
|
port_byte_out(0xA1, 0x0);
|
||||||
|
|
||||||
// Install the IRQs
|
// Install the IRQs
|
||||||
set_idt_gate(32, (u32)irq0);
|
set_idt_gate(32, (uint32_t)irq0);
|
||||||
set_idt_gate(33, (u32)irq1);
|
set_idt_gate(33, (uint32_t)irq1);
|
||||||
set_idt_gate(34, (u32)irq2);
|
set_idt_gate(34, (uint32_t)irq2);
|
||||||
set_idt_gate(35, (u32)irq3);
|
set_idt_gate(35, (uint32_t)irq3);
|
||||||
set_idt_gate(36, (u32)irq4);
|
set_idt_gate(36, (uint32_t)irq4);
|
||||||
set_idt_gate(37, (u32)irq5);
|
set_idt_gate(37, (uint32_t)irq5);
|
||||||
set_idt_gate(38, (u32)irq6);
|
set_idt_gate(38, (uint32_t)irq6);
|
||||||
set_idt_gate(39, (u32)irq7);
|
set_idt_gate(39, (uint32_t)irq7);
|
||||||
set_idt_gate(40, (u32)irq8);
|
set_idt_gate(40, (uint32_t)irq8);
|
||||||
set_idt_gate(41, (u32)irq9);
|
set_idt_gate(41, (uint32_t)irq9);
|
||||||
set_idt_gate(42, (u32)irq10);
|
set_idt_gate(42, (uint32_t)irq10);
|
||||||
set_idt_gate(43, (u32)irq11);
|
set_idt_gate(43, (uint32_t)irq11);
|
||||||
set_idt_gate(44, (u32)irq12);
|
set_idt_gate(44, (uint32_t)irq12);
|
||||||
set_idt_gate(45, (u32)irq13);
|
set_idt_gate(45, (uint32_t)irq13);
|
||||||
set_idt_gate(46, (u32)irq14);
|
set_idt_gate(46, (uint32_t)irq14);
|
||||||
set_idt_gate(47, (u32)irq15);
|
set_idt_gate(47, (uint32_t)irq15);
|
||||||
|
|
||||||
set_idt(); // Load with ASM
|
set_idt(); // Load with ASM
|
||||||
}
|
}
|
||||||
@ -126,7 +126,7 @@ void isr_handler(registers_t r) {
|
|||||||
kprint("\n");
|
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;
|
interrupt_handlers[n] = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#ifndef ISR_H
|
#ifndef ISR_H
|
||||||
#define ISR_H
|
#define ISR_H
|
||||||
|
|
||||||
#include "type.h"
|
#include <stdint.h>
|
||||||
|
|
||||||
/* ISRs reserved for CPU exceptions */
|
/* ISRs reserved for CPU exceptions */
|
||||||
extern void isr0();
|
extern void isr0();
|
||||||
@ -73,10 +73,10 @@ extern void irq15();
|
|||||||
|
|
||||||
/* Struct which aggregates many registers */
|
/* Struct which aggregates many registers */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 ds; /* Data segment selector */
|
uint32_t ds; /* Data segment selector */
|
||||||
u32 edi, esi, ebp, esp, ebx, edx, ecx, eax; /* Pushed by pusha. */
|
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; /* Pushed by pusha. */
|
||||||
u32 int_no, err_code; /* Interrupt number and error code (if applicable) */
|
uint32_t int_no, err_code; /* Interrupt number and error code (if applicable) */
|
||||||
u32 eip, cs, eflags, useresp, ss; /* Pushed by the processor automatically */
|
uint32_t eip, cs, eflags, useresp, ss; /* Pushed by the processor automatically */
|
||||||
} registers_t;
|
} registers_t;
|
||||||
|
|
||||||
void isr_install();
|
void isr_install();
|
||||||
@ -84,6 +84,6 @@ void isr_handler(registers_t r);
|
|||||||
void irq_install();
|
void irq_install();
|
||||||
|
|
||||||
typedef void (*isr_t)(registers_t);
|
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
|
#endif
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
/**
|
/**
|
||||||
* Read a byte from the specified port
|
* Read a byte from the specified port
|
||||||
*/
|
*/
|
||||||
u8 port_byte_in (u16 port) {
|
uint8_t port_byte_in (uint16_t port) {
|
||||||
u8 result;
|
uint8_t result;
|
||||||
/* Inline assembler syntax
|
/* Inline assembler syntax
|
||||||
* !! Notice how the source and destination registers are switched from NASM !!
|
* !! Notice how the source and destination registers are switched from NASM !!
|
||||||
*
|
*
|
||||||
@ -17,7 +17,7 @@ u8 port_byte_in (u16 port) {
|
|||||||
return result;
|
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
|
/* Notice how here both registers are mapped to C variables and
|
||||||
* nothing is returned, thus, no equals '=' in the asm syntax
|
* nothing is returned, thus, no equals '=' in the asm syntax
|
||||||
* However we see a comma since there are two variables in the input area
|
* 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));
|
__asm__ __volatile__("out %%al, %%dx" : : "a" (data), "d" (port));
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 port_word_in (u16 port) {
|
uint16_t port_word_in (uint16_t port) {
|
||||||
u16 result;
|
uint16_t result;
|
||||||
__asm__("in %%dx, %%ax" : "=a" (result) : "d" (port));
|
__asm__("in %%dx, %%ax" : "=a" (result) : "d" (port));
|
||||||
return result;
|
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));
|
__asm__ __volatile__("out %%ax, %%dx" : : "a" (data), "d" (port));
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
#ifndef PORTS_H
|
#ifndef PORTS_H
|
||||||
#define PORTS_H
|
#define PORTS_H
|
||||||
|
|
||||||
#include "../cpu/type.h"
|
#include <stdint.h>
|
||||||
|
|
||||||
unsigned char port_byte_in (u16 port);
|
unsigned char port_byte_in (uint16_t port);
|
||||||
void port_byte_out (u16 port, u8 data);
|
void port_byte_out (uint16_t port, uint8_t data);
|
||||||
unsigned short port_word_in (u16 port);
|
unsigned short port_word_in (uint16_t port);
|
||||||
void port_word_out (u16 port, u16 data);
|
void port_word_out (uint16_t port, uint16_t data);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -3,21 +3,21 @@
|
|||||||
#include "ports.h"
|
#include "ports.h"
|
||||||
#include "../libc/function.h"
|
#include "../libc/function.h"
|
||||||
|
|
||||||
u32 tick = 0;
|
uint32_t tick = 0;
|
||||||
|
|
||||||
static void timer_callback(registers_t regs) {
|
static void timer_callback(registers_t regs) {
|
||||||
tick++;
|
tick++;
|
||||||
UNUSED(regs);
|
UNUSED(regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_timer(u32 freq) {
|
void init_timer(uint32_t freq) {
|
||||||
/* Install the function we just wrote */
|
/* Install the function we just wrote */
|
||||||
register_interrupt_handler(IRQ0, timer_callback);
|
register_interrupt_handler(IRQ0, timer_callback);
|
||||||
|
|
||||||
/* Get the PIT value: hardware clock at 1193180 Hz */
|
/* Get the PIT value: hardware clock at 1193180 Hz */
|
||||||
u32 divisor = 1193180 / freq;
|
uint32_t divisor = 1193180 / freq;
|
||||||
u8 low = (u8)(divisor & 0xFF);
|
uint8_t low = (uint8_t)(divisor & 0xFF);
|
||||||
u8 high = (u8)( (divisor >> 8) & 0xFF);
|
uint8_t high = (uint8_t)( (divisor >> 8) & 0xFF);
|
||||||
/* Send the command */
|
/* Send the command */
|
||||||
port_byte_out(0x43, 0x36); /* Command port */
|
port_byte_out(0x43, 0x36); /* Command port */
|
||||||
port_byte_out(0x40, low);
|
port_byte_out(0x40, low);
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#ifndef TIMER_H
|
#ifndef TIMER_H
|
||||||
#define TIMER_H
|
#define TIMER_H
|
||||||
|
|
||||||
#include "type.h"
|
#include <stdint.h>
|
||||||
|
|
||||||
void init_timer(u32 freq);
|
void init_timer(uint32_t freq);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,16 +1,9 @@
|
|||||||
#ifndef TYPE_H
|
#ifndef TYPE_H
|
||||||
#define TYPE_H
|
#define TYPE_H
|
||||||
|
|
||||||
/* Instead of using 'chars' to allocate non-character bytes,
|
#include <stdint.h>
|
||||||
* 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;
|
|
||||||
|
|
||||||
#define low_16(address) (u16)((address) & 0xFFFF)
|
#define low_16(address) (uint16_t)((address) & 0xFFFF)
|
||||||
#define high_16(address) (u16)(((address) >> 16) & 0xFFFF)
|
#define high_16(address) (uint16_t)(((address) >> 16) & 0xFFFF)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include "../libc/string.h"
|
#include "../libc/string.h"
|
||||||
#include "../libc/function.h"
|
#include "../libc/function.h"
|
||||||
#include "../kernel/kernel.h"
|
#include "../kernel/kernel.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#define BACKSPACE 0x0E
|
#define BACKSPACE 0x0E
|
||||||
#define ENTER 0x1C
|
#define ENTER 0x1C
|
||||||
@ -26,7 +27,7 @@ const char sc_ascii[] = { '?', '?', '1', '2', '3', '4', '5', '6',
|
|||||||
|
|
||||||
static void keyboard_callback(registers_t regs) {
|
static void keyboard_callback(registers_t regs) {
|
||||||
/* The PIC leaves us the scancode in port 0x60 */
|
/* 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 > SC_MAX) return;
|
||||||
if (scancode == BACKSPACE) {
|
if (scancode == BACKSPACE) {
|
||||||
|
@ -1,3 +1 @@
|
|||||||
#include "../cpu/type.h"
|
|
||||||
|
|
||||||
void init_keyboard();
|
void init_keyboard();
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
#include "../cpu/ports.h"
|
#include "../cpu/ports.h"
|
||||||
#include "../libc/mem.h"
|
#include "../libc/mem.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
/* Declaration of private functions */
|
/* Declaration of private functions */
|
||||||
int get_cursor_offset();
|
int get_cursor_offset();
|
||||||
@ -65,7 +66,7 @@ void kprint_backspace() {
|
|||||||
* Sets the video cursor to the returned offset
|
* Sets the video cursor to the returned offset
|
||||||
*/
|
*/
|
||||||
int print_char(char c, int col, int row, char attr) {
|
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;
|
if (!attr) attr = WHITE_ON_BLACK;
|
||||||
|
|
||||||
/* Error control: print a red 'E' if the coords aren't right */
|
/* 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) {
|
if (offset >= MAX_ROWS * MAX_COLS * 2) {
|
||||||
int i;
|
int i;
|
||||||
for (i = 1; i < MAX_ROWS; i++)
|
for (i = 1; i < MAX_ROWS; i++)
|
||||||
memory_copy((u8*)(get_offset(0, i) + VIDEO_ADDRESS),
|
memory_copy((uint8_t*)(get_offset(0, i) + VIDEO_ADDRESS),
|
||||||
(u8*)(get_offset(0, i-1) + VIDEO_ADDRESS),
|
(uint8_t*)(get_offset(0, i-1) + VIDEO_ADDRESS),
|
||||||
MAX_COLS * 2);
|
MAX_COLS * 2);
|
||||||
|
|
||||||
/* Blank last line */
|
/* 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;
|
for (i = 0; i < MAX_COLS * 2; i++) last_line[i] = 0;
|
||||||
|
|
||||||
offset -= 2 * MAX_COLS;
|
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 */
|
/* Similar to get_cursor_offset, but instead of reading we write data */
|
||||||
offset /= 2;
|
offset /= 2;
|
||||||
port_byte_out(REG_SCREEN_CTRL, 14);
|
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_CTRL, 15);
|
||||||
port_byte_out(REG_SCREEN_DATA, (u8)(offset & 0xff));
|
port_byte_out(REG_SCREEN_DATA, (uint8_t)(offset & 0xff));
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear_screen() {
|
void clear_screen() {
|
||||||
int screen_size = MAX_COLS * MAX_ROWS;
|
int screen_size = MAX_COLS * MAX_ROWS;
|
||||||
int i;
|
int i;
|
||||||
u8 *screen = (u8*) VIDEO_ADDRESS;
|
uint8_t *screen = (uint8_t*) VIDEO_ADDRESS;
|
||||||
|
|
||||||
for (i = 0; i < screen_size; i++) {
|
for (i = 0; i < screen_size; i++) {
|
||||||
screen[i*2] = ' ';
|
screen[i*2] = ' ';
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
#ifndef SCREEN_H
|
#ifndef SCREEN_H
|
||||||
#define SCREEN_H
|
#define SCREEN_H
|
||||||
|
|
||||||
#include "../cpu/type.h"
|
|
||||||
|
|
||||||
#define VIDEO_ADDRESS 0xb8000
|
#define VIDEO_ADDRESS 0xb8000
|
||||||
#define MAX_ROWS 25
|
#define MAX_ROWS 25
|
||||||
#define MAX_COLS 80
|
#define MAX_COLS 80
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "kernel.h"
|
#include "kernel.h"
|
||||||
#include "../libc/string.h"
|
#include "../libc/string.h"
|
||||||
#include "../libc/mem.h"
|
#include "../libc/mem.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
void kernel_main() {
|
void kernel_main() {
|
||||||
isr_install();
|
isr_install();
|
||||||
@ -18,8 +19,8 @@ void user_input(char *input) {
|
|||||||
asm volatile("hlt");
|
asm volatile("hlt");
|
||||||
} else if (strcmp(input, "PAGE") == 0) {
|
} else if (strcmp(input, "PAGE") == 0) {
|
||||||
/* Lesson 22: Code to test kmalloc, the rest is unchanged */
|
/* Lesson 22: Code to test kmalloc, the rest is unchanged */
|
||||||
u32 phys_addr;
|
uint32_t phys_addr;
|
||||||
u32 page = kmalloc(1000, 1, &phys_addr);
|
uint32_t page = kmalloc(1000, 1, &phys_addr);
|
||||||
char page_str[16] = "";
|
char page_str[16] = "";
|
||||||
hex_to_ascii(page, page_str);
|
hex_to_ascii(page, page_str);
|
||||||
char phys_str[16] = "";
|
char phys_str[16] = "";
|
||||||
|
@ -1,24 +1,24 @@
|
|||||||
#include "mem.h"
|
#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;
|
int i;
|
||||||
for (i = 0; i < nbytes; i++) {
|
for (i = 0; i < nbytes; i++) {
|
||||||
*(dest + i) = *(source + i);
|
*(dest + i) = *(source + i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void memory_set(u8 *dest, u8 val, u32 len) {
|
void memory_set(uint8_t *dest, uint8_t val, uint32_t len) {
|
||||||
u8 *temp = (u8 *)dest;
|
uint8_t *temp = (uint8_t *)dest;
|
||||||
for ( ; len != 0; len--) *temp++ = val;
|
for ( ; len != 0; len--) *temp++ = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This should be computed at link time, but a hardcoded
|
/* This should be computed at link time, but a hardcoded
|
||||||
* value is fine for now. Remember that our kernel starts
|
* value is fine for now. Remember that our kernel starts
|
||||||
* at 0x1000 as defined on the Makefile */
|
* 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
|
/* Implementation is just a pointer to some free memory which
|
||||||
* keeps growing */
|
* 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 */
|
/* Pages are aligned to 4K, or 0x1000 */
|
||||||
if (align == 1 && (free_mem_addr & 0xFFFFF000)) {
|
if (align == 1 && (free_mem_addr & 0xFFFFF000)) {
|
||||||
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 */
|
/* Save also the physical address */
|
||||||
if (phys_addr) *phys_addr = free_mem_addr;
|
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 */
|
free_mem_addr += size; /* Remember to increment the pointer */
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
#ifndef MEM_H
|
#ifndef MEM_H
|
||||||
#define MEM_H
|
#define MEM_H
|
||||||
|
|
||||||
#include "../cpu/type.h"
|
#include <stdint.h>
|
||||||
|
|
||||||
void memory_copy(u8 *source, u8 *dest, int nbytes);
|
void memory_copy(uint8_t *source, uint8_t *dest, int nbytes);
|
||||||
void memory_set(u8 *dest, u8 val, u32 len);
|
void memory_set(uint8_t *dest, uint8_t val, uint32_t len);
|
||||||
|
|
||||||
/* At this stage there is no 'free' implemented. */
|
/* 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
|
#endif
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "../cpu/type.h"
|
#include <stdint.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* K&R implementation
|
* K&R implementation
|
||||||
@ -23,7 +23,7 @@ void hex_to_ascii(int n, char str[]) {
|
|||||||
append(str, 'x');
|
append(str, 'x');
|
||||||
char zeros = 0;
|
char zeros = 0;
|
||||||
|
|
||||||
s32 tmp;
|
int32_t tmp;
|
||||||
int i;
|
int i;
|
||||||
for (i = 28; i > 0; i -= 4) {
|
for (i = 28; i > 0; i -= 4) {
|
||||||
tmp = (n >> i) & 0xF;
|
tmp = (n >> i) & 0xF;
|
||||||
|
Loading…
Reference in New Issue
Block a user