fixed line endings on text files
git-svn-id: svn://anubis/hos/trunk@93 5b3e749e-e535-0410-8002-a9bb6afbdfca
This commit is contained in:
parent
ca82cc32ac
commit
24485b8143
@ -1,84 +1,84 @@
|
||||
|
||||
#include "k_bootstrap.h"
|
||||
#include "k_main.h"
|
||||
#include "hos_types.h"
|
||||
#include "hos_defines.h"
|
||||
#include "multiboot.h"
|
||||
#include "sys/cpu.h"
|
||||
#include "k_early_panic.h"
|
||||
#include "mm/mm.h"
|
||||
#include "lang/kio.h"
|
||||
#include "isr/interrupts.h"
|
||||
|
||||
#define DEBUG_LETTER(col,chr) *(u16_t *)(KERNEL_OFFSET + CONSOLE_MEMORY \
|
||||
+ 160 * 8 + (col) * 2) \
|
||||
= 0x0700 | (chr)
|
||||
extern "C" {
|
||||
|
||||
u8_t bootstrap_stack[4096];
|
||||
|
||||
/**************************************************************************
|
||||
* Multiboot header data block *
|
||||
*************************************************************************/
|
||||
u32_t mb_header[] __attribute__ ((section (".multiboot_header") )) = {
|
||||
MB_HEADER_MAGIC, /* magic */
|
||||
MB_HEADER_FLAGS, /* flags */
|
||||
-(MB_HEADER_MAGIC + MB_HEADER_FLAGS) /* checksum */
|
||||
};
|
||||
|
||||
/**************************************************************************
|
||||
* This function is invoked to bootstrap the kernel. *
|
||||
*************************************************************************/
|
||||
void k_bootstrap(mb_info_t * mb_info, u32_t mb_magic)
|
||||
{
|
||||
DEBUG_LETTER(1, 'b');
|
||||
|
||||
if (mb_magic != MB_BOOTLOADER_MAGIC)
|
||||
{
|
||||
k_early_panic("Bad multiboot magic identifier!");
|
||||
}
|
||||
|
||||
if ( ! (mb_info->flags & MB_BOOTLOADER_MMAP) )
|
||||
{
|
||||
k_early_panic("No memory map provided by bootloader!");
|
||||
}
|
||||
|
||||
for (mb_mmap_t * mmap = (mb_mmap_t *) (mb_info->mmap_addr + KERNEL_OFFSET),
|
||||
* end = (mb_mmap_t *) ((u32_t)mmap + mb_info->mmap_length);
|
||||
mmap < end;
|
||||
mmap = (mb_mmap_t *) (((u32_t)mmap) + mmap->size + 4))
|
||||
{
|
||||
// kprintf(" ** size: %d, type: %d ", mmap->size, mmap->type);
|
||||
mm_record_mmap_entry(mmap);
|
||||
}
|
||||
|
||||
DEBUG_LETTER(2, 'c');
|
||||
|
||||
/*
|
||||
* These functions could destroy the multiboot information block and
|
||||
* associated structures, so we must be finished reading those structures
|
||||
* before calling them.
|
||||
*/
|
||||
mm_bootstrap();
|
||||
DEBUG_LETTER(3, 'd');
|
||||
interrupts_bootstrap();
|
||||
DEBUG_LETTER(4, 'e');
|
||||
kio_bootstrap();
|
||||
DEBUG_LETTER(5, 'f');
|
||||
|
||||
/* begin using the permanent stack */
|
||||
write_esp(KERNEL_STACK_TOP);
|
||||
k_main();
|
||||
|
||||
idle_loop();
|
||||
}
|
||||
|
||||
void idle_loop()
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
__asm__ __volatile__ ("hlt");
|
||||
}
|
||||
}
|
||||
|
||||
} /* extern "C" */
|
||||
|
||||
#include "k_bootstrap.h"
|
||||
#include "k_main.h"
|
||||
#include "hos_types.h"
|
||||
#include "hos_defines.h"
|
||||
#include "multiboot.h"
|
||||
#include "sys/cpu.h"
|
||||
#include "k_early_panic.h"
|
||||
#include "mm/mm.h"
|
||||
#include "lang/kio.h"
|
||||
#include "isr/interrupts.h"
|
||||
|
||||
#define DEBUG_LETTER(col,chr) *(u16_t *)(KERNEL_OFFSET + CONSOLE_MEMORY \
|
||||
+ 160 * 8 + (col) * 2) \
|
||||
= 0x0700 | (chr)
|
||||
extern "C" {
|
||||
|
||||
u8_t bootstrap_stack[4096];
|
||||
|
||||
/**************************************************************************
|
||||
* Multiboot header data block *
|
||||
*************************************************************************/
|
||||
u32_t mb_header[] __attribute__ ((section (".multiboot_header") )) = {
|
||||
MB_HEADER_MAGIC, /* magic */
|
||||
MB_HEADER_FLAGS, /* flags */
|
||||
-(MB_HEADER_MAGIC + MB_HEADER_FLAGS) /* checksum */
|
||||
};
|
||||
|
||||
/**************************************************************************
|
||||
* This function is invoked to bootstrap the kernel. *
|
||||
*************************************************************************/
|
||||
void k_bootstrap(mb_info_t * mb_info, u32_t mb_magic)
|
||||
{
|
||||
DEBUG_LETTER(1, 'b');
|
||||
|
||||
if (mb_magic != MB_BOOTLOADER_MAGIC)
|
||||
{
|
||||
k_early_panic("Bad multiboot magic identifier!");
|
||||
}
|
||||
|
||||
if ( ! (mb_info->flags & MB_BOOTLOADER_MMAP) )
|
||||
{
|
||||
k_early_panic("No memory map provided by bootloader!");
|
||||
}
|
||||
|
||||
for (mb_mmap_t * mmap = (mb_mmap_t *) (mb_info->mmap_addr + KERNEL_OFFSET),
|
||||
* end = (mb_mmap_t *) ((u32_t)mmap + mb_info->mmap_length);
|
||||
mmap < end;
|
||||
mmap = (mb_mmap_t *) (((u32_t)mmap) + mmap->size + 4))
|
||||
{
|
||||
// kprintf(" ** size: %d, type: %d ", mmap->size, mmap->type);
|
||||
mm_record_mmap_entry(mmap);
|
||||
}
|
||||
|
||||
DEBUG_LETTER(2, 'c');
|
||||
|
||||
/*
|
||||
* These functions could destroy the multiboot information block and
|
||||
* associated structures, so we must be finished reading those structures
|
||||
* before calling them.
|
||||
*/
|
||||
mm_bootstrap();
|
||||
DEBUG_LETTER(3, 'd');
|
||||
interrupts_bootstrap();
|
||||
DEBUG_LETTER(4, 'e');
|
||||
kio_bootstrap();
|
||||
DEBUG_LETTER(5, 'f');
|
||||
|
||||
/* begin using the permanent stack */
|
||||
write_esp(KERNEL_STACK_TOP);
|
||||
k_main();
|
||||
|
||||
idle_loop();
|
||||
}
|
||||
|
||||
void idle_loop()
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
__asm__ __volatile__ ("hlt");
|
||||
}
|
||||
}
|
||||
|
||||
} /* extern "C" */
|
||||
|
@ -1,18 +1,18 @@
|
||||
|
||||
#include "hos_types.h"
|
||||
#include "hos_defines.h"
|
||||
#include "k_early_panic.h"
|
||||
|
||||
void k_early_panic(const char * msg)
|
||||
{
|
||||
char * dest = (char *) (CONSOLE_MEMORY + KERNEL_OFFSET);
|
||||
while (*msg)
|
||||
{
|
||||
*dest++ = *msg++;
|
||||
*dest++ = 0x04; /* red error message */
|
||||
}
|
||||
|
||||
/* infinite loop */
|
||||
for (;;)
|
||||
;
|
||||
}
|
||||
|
||||
#include "hos_types.h"
|
||||
#include "hos_defines.h"
|
||||
#include "k_early_panic.h"
|
||||
|
||||
void k_early_panic(const char * msg)
|
||||
{
|
||||
char * dest = (char *) (CONSOLE_MEMORY + KERNEL_OFFSET);
|
||||
while (*msg)
|
||||
{
|
||||
*dest++ = *msg++;
|
||||
*dest++ = 0x04; /* red error message */
|
||||
}
|
||||
|
||||
/* infinite loop */
|
||||
for (;;)
|
||||
;
|
||||
}
|
||||
|
@ -1,15 +1,15 @@
|
||||
|
||||
#ifndef K_EARLY_PANIC_H
|
||||
#define K_EARLY_PANIC_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void k_early_panic(const char * msg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef K_EARLY_PANIC_H
|
||||
#define K_EARLY_PANIC_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void k_early_panic(const char * msg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -1,49 +1,49 @@
|
||||
|
||||
#ifndef HOS_DEFINES_H
|
||||
#define HOS_DEFINES_H
|
||||
|
||||
#include "hos_types.h"
|
||||
|
||||
#define KERNEL_OFFSET 0x00000000
|
||||
|
||||
#define PAGE_LOG_SIZE 12
|
||||
#define PAGE_SIZE (1 << PAGE_LOG_SIZE)
|
||||
#define PAGE_HIGH_MASK (0xFFFFFFFFu << PAGE_LOG_SIZE)
|
||||
#define PAGE_LOW_MASK (0xFFFFFFFFu >> (32 - PAGE_LOG_SIZE))
|
||||
|
||||
#define CONSOLE_MEMORY 0xB8000
|
||||
|
||||
#define KERNEL_CODE (&_code)
|
||||
#define KERNEL_DATA (&_data)
|
||||
#define KERNEL_BSS (&_bss)
|
||||
#define KERNEL_END (&_end)
|
||||
|
||||
#define KERNEL_PHYSICAL_ADDRESS ((u32_t)(KERNEL_CODE - KERNEL_OFFSET))
|
||||
#define KERNEL_VIRTUAL_ADDRESS ((u32_t)KERNEL_CODE)
|
||||
#define KERNEL_SIZE ((u32_t)(KERNEL_END - KERNEL_CODE))
|
||||
|
||||
#define KERNEL_STACK_TOP 0x20000000
|
||||
|
||||
#define KERNEL_TIMER_FREQ 1000
|
||||
|
||||
#define BUILD_BUG_ON(condition) \
|
||||
do { \
|
||||
typedef struct { int negative_width_test : ((condition)?-1:1); } \
|
||||
BUILD_BUG_ON_DUMMY_STRUCT; \
|
||||
} \
|
||||
while(0)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern u8_t _code;
|
||||
extern u8_t _data;
|
||||
extern u8_t _bss;
|
||||
extern u8_t _end;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef HOS_DEFINES_H
|
||||
#define HOS_DEFINES_H
|
||||
|
||||
#include "hos_types.h"
|
||||
|
||||
#define KERNEL_OFFSET 0x00000000
|
||||
|
||||
#define PAGE_LOG_SIZE 12
|
||||
#define PAGE_SIZE (1 << PAGE_LOG_SIZE)
|
||||
#define PAGE_HIGH_MASK (0xFFFFFFFFu << PAGE_LOG_SIZE)
|
||||
#define PAGE_LOW_MASK (0xFFFFFFFFu >> (32 - PAGE_LOG_SIZE))
|
||||
|
||||
#define CONSOLE_MEMORY 0xB8000
|
||||
|
||||
#define KERNEL_CODE (&_code)
|
||||
#define KERNEL_DATA (&_data)
|
||||
#define KERNEL_BSS (&_bss)
|
||||
#define KERNEL_END (&_end)
|
||||
|
||||
#define KERNEL_PHYSICAL_ADDRESS ((u32_t)(KERNEL_CODE - KERNEL_OFFSET))
|
||||
#define KERNEL_VIRTUAL_ADDRESS ((u32_t)KERNEL_CODE)
|
||||
#define KERNEL_SIZE ((u32_t)(KERNEL_END - KERNEL_CODE))
|
||||
|
||||
#define KERNEL_STACK_TOP 0x20000000
|
||||
|
||||
#define KERNEL_TIMER_FREQ 1000
|
||||
|
||||
#define BUILD_BUG_ON(condition) \
|
||||
do { \
|
||||
typedef struct { int negative_width_test : ((condition)?-1:1); } \
|
||||
BUILD_BUG_ON_DUMMY_STRUCT; \
|
||||
} \
|
||||
while(0)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern u8_t _code;
|
||||
extern u8_t _data;
|
||||
extern u8_t _bss;
|
||||
extern u8_t _end;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -1,55 +1,55 @@
|
||||
|
||||
#ifndef HOS_TYPES_H
|
||||
#define HOS_TYPES_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef unsigned char u8_t;
|
||||
typedef signed char s8_t;
|
||||
typedef unsigned short u16_t;
|
||||
typedef signed short s16_t;
|
||||
typedef unsigned int u32_t;
|
||||
typedef signed int s32_t;
|
||||
typedef unsigned long long u64_t;
|
||||
typedef signed long long s64_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32_t gs;
|
||||
u32_t fs;
|
||||
u32_t es;
|
||||
u32_t ds;
|
||||
|
||||
u32_t edi;
|
||||
u32_t esi;
|
||||
u32_t ebp;
|
||||
u32_t esp_junk; /* the esp value saved by 'pusha' */
|
||||
u32_t ebx;
|
||||
u32_t edx;
|
||||
u32_t ecx;
|
||||
u32_t eax;
|
||||
|
||||
u32_t error; /* valid on exceptions 8, 10-14 */
|
||||
|
||||
u32_t eip;
|
||||
u32_t cs;
|
||||
u32_t eflags;
|
||||
u32_t esp; /* present if privilege transition */
|
||||
u32_t ss;
|
||||
} int_stack_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u16_t limit;
|
||||
u32_t base;
|
||||
} __attribute__ ((packed)) gdtr_t;
|
||||
|
||||
typedef gdtr_t idtr_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef HOS_TYPES_H
|
||||
#define HOS_TYPES_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef unsigned char u8_t;
|
||||
typedef signed char s8_t;
|
||||
typedef unsigned short u16_t;
|
||||
typedef signed short s16_t;
|
||||
typedef unsigned int u32_t;
|
||||
typedef signed int s32_t;
|
||||
typedef unsigned long long u64_t;
|
||||
typedef signed long long s64_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32_t gs;
|
||||
u32_t fs;
|
||||
u32_t es;
|
||||
u32_t ds;
|
||||
|
||||
u32_t edi;
|
||||
u32_t esi;
|
||||
u32_t ebp;
|
||||
u32_t esp_junk; /* the esp value saved by 'pusha' */
|
||||
u32_t ebx;
|
||||
u32_t edx;
|
||||
u32_t ecx;
|
||||
u32_t eax;
|
||||
|
||||
u32_t error; /* valid on exceptions 8, 10-14 */
|
||||
|
||||
u32_t eip;
|
||||
u32_t cs;
|
||||
u32_t eflags;
|
||||
u32_t esp; /* present if privilege transition */
|
||||
u32_t ss;
|
||||
} int_stack_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u16_t limit;
|
||||
u32_t base;
|
||||
} __attribute__ ((packed)) gdtr_t;
|
||||
|
||||
typedef gdtr_t idtr_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -1,37 +1,37 @@
|
||||
|
||||
#ifndef PORTIO_H
|
||||
#define PORTIO_H
|
||||
|
||||
#include "hos_types.h"
|
||||
|
||||
#define outportb(port, val) \
|
||||
__asm__ __volatile__ ("outb %%al, %%dx" : : "a" (val), "d" (port));
|
||||
|
||||
#define outportw(port, val) \
|
||||
__asm__ __volatile__ ("outw %%ax, %%dx" : : "a" (val), "d" (port));
|
||||
|
||||
#define outportd(port, val) \
|
||||
__asm__ __volatile__ ("outl %%eax, %%dx" : : "a" (val), "d" (port));
|
||||
|
||||
static inline u8_t inportb(u16_t port)
|
||||
{
|
||||
u8_t val;
|
||||
__asm__ __volatile__ ("inb %%dx, %%al" : "=a" (val) : "d" (port));
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline u16_t inportw(u16_t port)
|
||||
{
|
||||
u16_t val;
|
||||
__asm__ __volatile__ ("inw %%dx, %%al" : "=a" (val) : "d" (port));
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline u32_t inportd(u16_t port)
|
||||
{
|
||||
u32_t val;
|
||||
__asm__ __volatile__ ("inl %%dx, %%al" : "=a" (val) : "d" (port));
|
||||
return val;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef PORTIO_H
|
||||
#define PORTIO_H
|
||||
|
||||
#include "hos_types.h"
|
||||
|
||||
#define outportb(port, val) \
|
||||
__asm__ __volatile__ ("outb %%al, %%dx" : : "a" (val), "d" (port));
|
||||
|
||||
#define outportw(port, val) \
|
||||
__asm__ __volatile__ ("outw %%ax, %%dx" : : "a" (val), "d" (port));
|
||||
|
||||
#define outportd(port, val) \
|
||||
__asm__ __volatile__ ("outl %%eax, %%dx" : : "a" (val), "d" (port));
|
||||
|
||||
static inline u8_t inportb(u16_t port)
|
||||
{
|
||||
u8_t val;
|
||||
__asm__ __volatile__ ("inb %%dx, %%al" : "=a" (val) : "d" (port));
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline u16_t inportw(u16_t port)
|
||||
{
|
||||
u16_t val;
|
||||
__asm__ __volatile__ ("inw %%dx, %%al" : "=a" (val) : "d" (port));
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline u32_t inportd(u16_t port)
|
||||
{
|
||||
u32_t val;
|
||||
__asm__ __volatile__ ("inl %%dx, %%al" : "=a" (val) : "d" (port));
|
||||
return val;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,107 +1,107 @@
|
||||
|
||||
#include "hos_types.h"
|
||||
#include "interrupts.h"
|
||||
#include "mm/mm.h"
|
||||
#include "lang/kio.h"
|
||||
#include "sys/pic.h"
|
||||
#include "sys/cpu.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
idtr_t idtr;
|
||||
|
||||
void isr(u8_t int_num, int_stack_t * istack)
|
||||
{
|
||||
switch (int_num)
|
||||
{
|
||||
case 0x20: /* timer interrupt */
|
||||
(*(u16_t *)CONSOLE_MEMORY)++;
|
||||
pic_eoi();
|
||||
break;
|
||||
case 0x21:
|
||||
/* TODO: keyboard hook */
|
||||
pic_eoi();
|
||||
break;
|
||||
default:
|
||||
kputs("--------------------------------------------------------------------------------");
|
||||
kprintf("Unhandled Interrupt #%d\n", int_num);
|
||||
kprintf(" ds: 0x%08x es: 0x%08x fs: 0x%08x gs: 0x%08x\n",
|
||||
istack->ds, istack->es, istack->fs, istack->gs);
|
||||
kprintf(" eax: 0x%08x ebx: 0x%08x ecx: 0x%08x edx: 0x%08x\n",
|
||||
istack->eax, istack->ebx, istack->ecx, istack->edx);
|
||||
kprintf(" ebp: 0x%08x esi: 0x%08x edi: 0x%08x eflags: 0x%08x\n",
|
||||
istack->ebp, istack->esi, istack->edi, istack->eflags);
|
||||
kprintf(" cs: 0x%08x eip: 0x%08x ss: 0x%08x esp: 0x%08x\n",
|
||||
istack->cs, istack->eip, istack->ss, istack->esp);
|
||||
kprintf(" cr0: 0x%08x cr2: 0x%08x cr3: 0x%08x\n",
|
||||
read_cr0(), read_cr2(), read_cr3());
|
||||
kprintf(" Error: 0x%08x (%d)\n", istack->error, istack->error);
|
||||
kputs("--------------------------------------------------------------------------------");
|
||||
|
||||
kprintf("Halting!\n");
|
||||
for (;;)
|
||||
;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} /* extern "C" */
|
||||
|
||||
void interrupts_bootstrap()
|
||||
{
|
||||
u32_t idt_base = mm_page_alloc();
|
||||
u64_t * idt = (u64_t *) (idt_base + KERNEL_OFFSET);
|
||||
idt[0] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_0, 0);
|
||||
idt[1] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_1, 0);
|
||||
idt[2] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_2, 0);
|
||||
idt[3] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_3, 0);
|
||||
idt[4] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_4, 0);
|
||||
idt[5] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_5, 0);
|
||||
idt[6] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_6, 0);
|
||||
idt[7] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_7, 0);
|
||||
idt[8] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_8, 0);
|
||||
idt[9] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_9, 0);
|
||||
idt[10] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_10, 0);
|
||||
idt[11] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_11, 0);
|
||||
idt[12] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_12, 0);
|
||||
idt[13] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_13, 0);
|
||||
idt[14] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_14, 0);
|
||||
idt[15] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_15, 0);
|
||||
idt[16] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_16, 0);
|
||||
idt[17] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_17, 0);
|
||||
idt[18] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_18, 0);
|
||||
idt[19] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_19, 0);
|
||||
idt[20] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_20, 0);
|
||||
idt[21] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_21, 0);
|
||||
idt[22] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_22, 0);
|
||||
idt[23] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_23, 0);
|
||||
idt[24] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_24, 0);
|
||||
idt[25] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_25, 0);
|
||||
idt[26] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_26, 0);
|
||||
idt[27] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_27, 0);
|
||||
idt[28] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_28, 0);
|
||||
idt[29] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_29, 0);
|
||||
idt[30] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_30, 0);
|
||||
idt[31] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_31, 0);
|
||||
idt[32] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_32, 0);
|
||||
idt[33] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_33, 0);
|
||||
idt[34] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_34, 0);
|
||||
idt[35] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_35, 0);
|
||||
idt[36] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_36, 0);
|
||||
idt[37] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_37, 0);
|
||||
idt[38] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_38, 0);
|
||||
idt[39] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_39, 0);
|
||||
idt[40] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_40, 0);
|
||||
idt[41] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_41, 0);
|
||||
idt[42] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_42, 0);
|
||||
idt[43] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_43, 0);
|
||||
idt[44] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_44, 0);
|
||||
idt[45] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_45, 0);
|
||||
idt[46] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_46, 0);
|
||||
idt[47] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_47, 0);
|
||||
idt[48] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_48, 0);
|
||||
idt[49] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_49, 0);
|
||||
idtr.base = idt_base;
|
||||
idtr.limit = 49 * sizeof(idt[0]) - 1;
|
||||
__asm__ __volatile__ ("lidt (idtr)");
|
||||
}
|
||||
|
||||
#include "hos_types.h"
|
||||
#include "interrupts.h"
|
||||
#include "mm/mm.h"
|
||||
#include "lang/kio.h"
|
||||
#include "sys/pic.h"
|
||||
#include "sys/cpu.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
idtr_t idtr;
|
||||
|
||||
void isr(u8_t int_num, int_stack_t * istack)
|
||||
{
|
||||
switch (int_num)
|
||||
{
|
||||
case 0x20: /* timer interrupt */
|
||||
(*(u16_t *)CONSOLE_MEMORY)++;
|
||||
pic_eoi();
|
||||
break;
|
||||
case 0x21:
|
||||
/* TODO: keyboard hook */
|
||||
pic_eoi();
|
||||
break;
|
||||
default:
|
||||
kputs("--------------------------------------------------------------------------------");
|
||||
kprintf("Unhandled Interrupt #%d\n", int_num);
|
||||
kprintf(" ds: 0x%08x es: 0x%08x fs: 0x%08x gs: 0x%08x\n",
|
||||
istack->ds, istack->es, istack->fs, istack->gs);
|
||||
kprintf(" eax: 0x%08x ebx: 0x%08x ecx: 0x%08x edx: 0x%08x\n",
|
||||
istack->eax, istack->ebx, istack->ecx, istack->edx);
|
||||
kprintf(" ebp: 0x%08x esi: 0x%08x edi: 0x%08x eflags: 0x%08x\n",
|
||||
istack->ebp, istack->esi, istack->edi, istack->eflags);
|
||||
kprintf(" cs: 0x%08x eip: 0x%08x ss: 0x%08x esp: 0x%08x\n",
|
||||
istack->cs, istack->eip, istack->ss, istack->esp);
|
||||
kprintf(" cr0: 0x%08x cr2: 0x%08x cr3: 0x%08x\n",
|
||||
read_cr0(), read_cr2(), read_cr3());
|
||||
kprintf(" Error: 0x%08x (%d)\n", istack->error, istack->error);
|
||||
kputs("--------------------------------------------------------------------------------");
|
||||
|
||||
kprintf("Halting!\n");
|
||||
for (;;)
|
||||
;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} /* extern "C" */
|
||||
|
||||
void interrupts_bootstrap()
|
||||
{
|
||||
u32_t idt_base = mm_page_alloc();
|
||||
u64_t * idt = (u64_t *) (idt_base + KERNEL_OFFSET);
|
||||
idt[0] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_0, 0);
|
||||
idt[1] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_1, 0);
|
||||
idt[2] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_2, 0);
|
||||
idt[3] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_3, 0);
|
||||
idt[4] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_4, 0);
|
||||
idt[5] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_5, 0);
|
||||
idt[6] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_6, 0);
|
||||
idt[7] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_7, 0);
|
||||
idt[8] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_8, 0);
|
||||
idt[9] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_9, 0);
|
||||
idt[10] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_10, 0);
|
||||
idt[11] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_11, 0);
|
||||
idt[12] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_12, 0);
|
||||
idt[13] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_13, 0);
|
||||
idt[14] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_14, 0);
|
||||
idt[15] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_15, 0);
|
||||
idt[16] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_16, 0);
|
||||
idt[17] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_17, 0);
|
||||
idt[18] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_18, 0);
|
||||
idt[19] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_19, 0);
|
||||
idt[20] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_20, 0);
|
||||
idt[21] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_21, 0);
|
||||
idt[22] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_22, 0);
|
||||
idt[23] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_23, 0);
|
||||
idt[24] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_24, 0);
|
||||
idt[25] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_25, 0);
|
||||
idt[26] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_26, 0);
|
||||
idt[27] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_27, 0);
|
||||
idt[28] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_28, 0);
|
||||
idt[29] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_29, 0);
|
||||
idt[30] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_30, 0);
|
||||
idt[31] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_31, 0);
|
||||
idt[32] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_32, 0);
|
||||
idt[33] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_33, 0);
|
||||
idt[34] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_34, 0);
|
||||
idt[35] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_35, 0);
|
||||
idt[36] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_36, 0);
|
||||
idt[37] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_37, 0);
|
||||
idt[38] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_38, 0);
|
||||
idt[39] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_39, 0);
|
||||
idt[40] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_40, 0);
|
||||
idt[41] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_41, 0);
|
||||
idt[42] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_42, 0);
|
||||
idt[43] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_43, 0);
|
||||
idt[44] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_44, 0);
|
||||
idt[45] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_45, 0);
|
||||
idt[46] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_46, 0);
|
||||
idt[47] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_47, 0);
|
||||
idt[48] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_48, 0);
|
||||
idt[49] = MAKE_IDT_DESCRIPTOR(KERNEL_CODE_SEGMENT, isr_49, 0);
|
||||
idtr.base = idt_base;
|
||||
idtr.limit = 49 * sizeof(idt[0]) - 1;
|
||||
__asm__ __volatile__ ("lidt (idtr)");
|
||||
}
|
||||
|
@ -1,79 +1,79 @@
|
||||
|
||||
#ifndef INTERRUPTS_H
|
||||
#define INTERRUPTS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void isr(u8_t int_num, int_stack_t * int_stack);
|
||||
|
||||
extern void isr_0();
|
||||
extern void isr_1();
|
||||
extern void isr_2();
|
||||
extern void isr_3();
|
||||
extern void isr_4();
|
||||
extern void isr_5();
|
||||
extern void isr_6();
|
||||
extern void isr_7();
|
||||
extern void isr_8();
|
||||
extern void isr_9();
|
||||
extern void isr_10();
|
||||
extern void isr_11();
|
||||
extern void isr_12();
|
||||
extern void isr_13();
|
||||
extern void isr_14();
|
||||
extern void isr_15();
|
||||
extern void isr_16();
|
||||
extern void isr_17();
|
||||
extern void isr_18();
|
||||
extern void isr_19();
|
||||
extern void isr_20();
|
||||
extern void isr_21();
|
||||
extern void isr_22();
|
||||
extern void isr_23();
|
||||
extern void isr_24();
|
||||
extern void isr_25();
|
||||
extern void isr_26();
|
||||
extern void isr_27();
|
||||
extern void isr_28();
|
||||
extern void isr_29();
|
||||
extern void isr_30();
|
||||
extern void isr_31();
|
||||
extern void isr_32();
|
||||
extern void isr_33();
|
||||
extern void isr_34();
|
||||
extern void isr_35();
|
||||
extern void isr_36();
|
||||
extern void isr_37();
|
||||
extern void isr_38();
|
||||
extern void isr_39();
|
||||
extern void isr_40();
|
||||
extern void isr_41();
|
||||
extern void isr_42();
|
||||
extern void isr_43();
|
||||
extern void isr_44();
|
||||
extern void isr_45();
|
||||
extern void isr_46();
|
||||
extern void isr_47();
|
||||
extern void isr_48();
|
||||
extern void isr_49();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define MAKE_IDT_DESCRIPTOR(selector, offset, dpl) \
|
||||
(u64_t) ( ( (((u64_t) offset) & 0xFFFF0000ull) << 32 ) /* offset 31:16 */ \
|
||||
| ( ( (u64_t) 0x1ull) << 47 ) /* present */ \
|
||||
| ( (((u64_t) dpl) & 0x3) << 45 ) /* DPL */ \
|
||||
| ( ( (u64_t) 0xEull) << 40 ) /* TODO: gate? */ \
|
||||
| ( (((u64_t) selector) & 0xFFFFull) << 16 ) /* selector */ \
|
||||
| ( (((u64_t) offset) & 0x0000FFFFull) ) ) /* offset 15:0 */
|
||||
|
||||
void interrupts_bootstrap();
|
||||
|
||||
#define interrupts_enable() __asm__ __volatile__ ("sti");
|
||||
#define interrupts_disable() __asm__ __volatile__ ("cli");
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef INTERRUPTS_H
|
||||
#define INTERRUPTS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void isr(u8_t int_num, int_stack_t * int_stack);
|
||||
|
||||
extern void isr_0();
|
||||
extern void isr_1();
|
||||
extern void isr_2();
|
||||
extern void isr_3();
|
||||
extern void isr_4();
|
||||
extern void isr_5();
|
||||
extern void isr_6();
|
||||
extern void isr_7();
|
||||
extern void isr_8();
|
||||
extern void isr_9();
|
||||
extern void isr_10();
|
||||
extern void isr_11();
|
||||
extern void isr_12();
|
||||
extern void isr_13();
|
||||
extern void isr_14();
|
||||
extern void isr_15();
|
||||
extern void isr_16();
|
||||
extern void isr_17();
|
||||
extern void isr_18();
|
||||
extern void isr_19();
|
||||
extern void isr_20();
|
||||
extern void isr_21();
|
||||
extern void isr_22();
|
||||
extern void isr_23();
|
||||
extern void isr_24();
|
||||
extern void isr_25();
|
||||
extern void isr_26();
|
||||
extern void isr_27();
|
||||
extern void isr_28();
|
||||
extern void isr_29();
|
||||
extern void isr_30();
|
||||
extern void isr_31();
|
||||
extern void isr_32();
|
||||
extern void isr_33();
|
||||
extern void isr_34();
|
||||
extern void isr_35();
|
||||
extern void isr_36();
|
||||
extern void isr_37();
|
||||
extern void isr_38();
|
||||
extern void isr_39();
|
||||
extern void isr_40();
|
||||
extern void isr_41();
|
||||
extern void isr_42();
|
||||
extern void isr_43();
|
||||
extern void isr_44();
|
||||
extern void isr_45();
|
||||
extern void isr_46();
|
||||
extern void isr_47();
|
||||
extern void isr_48();
|
||||
extern void isr_49();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define MAKE_IDT_DESCRIPTOR(selector, offset, dpl) \
|
||||
(u64_t) ( ( (((u64_t) offset) & 0xFFFF0000ull) << 32 ) /* offset 31:16 */ \
|
||||
| ( ( (u64_t) 0x1ull) << 47 ) /* present */ \
|
||||
| ( (((u64_t) dpl) & 0x3) << 45 ) /* DPL */ \
|
||||
| ( ( (u64_t) 0xEull) << 40 ) /* TODO: gate? */ \
|
||||
| ( (((u64_t) selector) & 0xFFFFull) << 16 ) /* selector */ \
|
||||
| ( (((u64_t) offset) & 0x0000FFFFull) ) ) /* offset 15:0 */
|
||||
|
||||
void interrupts_bootstrap();
|
||||
|
||||
#define interrupts_enable() __asm__ __volatile__ ("sti");
|
||||
#define interrupts_disable() __asm__ __volatile__ ("cli");
|
||||
|
||||
#endif
|
||||
|
@ -1,56 +1,56 @@
|
||||
|
||||
; C ISR routine
|
||||
[extern isr]
|
||||
|
||||
|
||||
; Macro for creating a single ISR label
|
||||
; We need to push a junk value on the stack first
|
||||
; if the interrupt number is not 8 or 10-14.
|
||||
; This is to properly align the stack for both exceptions
|
||||
; having and not having error codes.
|
||||
%macro isr_label 1
|
||||
[global isr_%1]
|
||||
isr_%1:
|
||||
%if ( (%1 != 8) && (%1 < 10 || %1 > 14) )
|
||||
push eax ; junk value to take error code stack space
|
||||
%endif
|
||||
pusha ; eax, ecx, edx, ebx, esp, ebp, esi, edi
|
||||
mov al, %1 ; save interrupt number in al
|
||||
%if ($ - isr_common) < 127 ; do a short jump and save 3 bytes if we can
|
||||
jmp short isr_common
|
||||
%else
|
||||
jmp isr_common
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
|
||||
; The common ISR routine
|
||||
isr_common:
|
||||
push ds
|
||||
push es
|
||||
push fs
|
||||
push gs
|
||||
|
||||
push esp ; pointer to interrupt stack
|
||||
push eax ; interrupt number
|
||||
call isr
|
||||
pop eax ; restore stack pointer (this is shorter
|
||||
pop eax ; than "add esp, 8" and "lea esp, [esp+8]")
|
||||
|
||||
pop gs
|
||||
pop fs
|
||||
pop es
|
||||
pop ds
|
||||
popa ; edi, esi, ebp, <null>, ebx, edx, ecx, eax
|
||||
lea esp, [esp+4] ; bypass error code
|
||||
|
||||
iret
|
||||
|
||||
|
||||
; Loop to create all of our ISR entry points
|
||||
%assign i 0
|
||||
%rep 50
|
||||
isr_label i
|
||||
%assign i i+1
|
||||
%endrep
|
||||
|
||||
|
||||
; C ISR routine
|
||||
[extern isr]
|
||||
|
||||
|
||||
; Macro for creating a single ISR label
|
||||
; We need to push a junk value on the stack first
|
||||
; if the interrupt number is not 8 or 10-14.
|
||||
; This is to properly align the stack for both exceptions
|
||||
; having and not having error codes.
|
||||
%macro isr_label 1
|
||||
[global isr_%1]
|
||||
isr_%1:
|
||||
%if ( (%1 != 8) && (%1 < 10 || %1 > 14) )
|
||||
push eax ; junk value to take error code stack space
|
||||
%endif
|
||||
pusha ; eax, ecx, edx, ebx, esp, ebp, esi, edi
|
||||
mov al, %1 ; save interrupt number in al
|
||||
%if ($ - isr_common) < 127 ; do a short jump and save 3 bytes if we can
|
||||
jmp short isr_common
|
||||
%else
|
||||
jmp isr_common
|
||||
%endif
|
||||
%endmacro
|
||||
|
||||
|
||||
; The common ISR routine
|
||||
isr_common:
|
||||
push ds
|
||||
push es
|
||||
push fs
|
||||
push gs
|
||||
|
||||
push esp ; pointer to interrupt stack
|
||||
push eax ; interrupt number
|
||||
call isr
|
||||
pop eax ; restore stack pointer (this is shorter
|
||||
pop eax ; than "add esp, 8" and "lea esp, [esp+8]")
|
||||
|
||||
pop gs
|
||||
pop fs
|
||||
pop es
|
||||
pop ds
|
||||
popa ; edi, esi, ebp, <null>, ebx, edx, ecx, eax
|
||||
lea esp, [esp+4] ; bypass error code
|
||||
|
||||
iret
|
||||
|
||||
|
||||
; Loop to create all of our ISR entry points
|
||||
%assign i 0
|
||||
%rep 50
|
||||
isr_label i
|
||||
%assign i i+1
|
||||
%endrep
|
||||
|
||||
|
@ -1,317 +1,317 @@
|
||||
|
||||
#include "hos_types.h"
|
||||
#include "hos_defines.h"
|
||||
#include "kio.h"
|
||||
#include "string.h"
|
||||
#include "portio.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdarg.h> /* va_*() */
|
||||
|
||||
static void fmt_d2a(char * buf, int val);
|
||||
static void fmt_u2a(char * buf, unsigned int val);
|
||||
static void fmt_ll2a(char * buf, long long val);
|
||||
static void fmt_ull2a(char * buf, unsigned long long val);
|
||||
static void fmt_x2a(char * buf, unsigned int val);
|
||||
static void fmt_xl2a(char * buf, unsigned long long val);
|
||||
static void fmt_o2a(char * buf, unsigned int val);
|
||||
|
||||
static int cursor_x, cursor_y;
|
||||
|
||||
static void writeCursorPosition(int x, int y)
|
||||
{
|
||||
u16_t pos = 80 * y + x;
|
||||
outportb(0x3D4, 0x0E);
|
||||
outportb(0x3D5, pos >> 8);
|
||||
outportb(0x3D4, 0x0F);
|
||||
outportb(0x3D5, pos);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
void kio_bootstrap()
|
||||
{
|
||||
cursor_x = 0;
|
||||
cursor_y = 9;
|
||||
writeCursorPosition(cursor_x, cursor_y);
|
||||
}
|
||||
|
||||
void kprintf(const char * fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
|
||||
kvprintf(fmt, args);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void kvprintf(const char * fmt, va_list args)
|
||||
{
|
||||
char tmpbuf[25];
|
||||
for ( ; *fmt; fmt++)
|
||||
{
|
||||
if (*fmt == '%')
|
||||
{
|
||||
fmt++;
|
||||
if (*fmt)
|
||||
{
|
||||
int width = 0;
|
||||
char pad_char = ' ';
|
||||
bool pad_right = false;
|
||||
if (*fmt == '0')
|
||||
{
|
||||
pad_char = '0';
|
||||
fmt++;
|
||||
}
|
||||
else if (*fmt == '-')
|
||||
{
|
||||
pad_right = true;
|
||||
fmt++;
|
||||
}
|
||||
for ( ; '0' <= *fmt && *fmt <= '9'; fmt++)
|
||||
{
|
||||
if (width == 0)
|
||||
{
|
||||
width = *fmt - '0';
|
||||
}
|
||||
else
|
||||
{
|
||||
width *= 10;
|
||||
width += *fmt - '0';
|
||||
}
|
||||
}
|
||||
switch (*fmt)
|
||||
{
|
||||
case 'c':
|
||||
kputc(va_arg(args, int));
|
||||
break;
|
||||
case 'd':
|
||||
fmt_d2a(tmpbuf, va_arg(args, int));
|
||||
kputs_pad(tmpbuf, width, pad_char, pad_right);
|
||||
break;
|
||||
case 'l':
|
||||
fmt_ll2a(tmpbuf, va_arg(args, long long));
|
||||
kputs_pad(tmpbuf, width, pad_char, pad_right);
|
||||
break;
|
||||
case 'L':
|
||||
fmt_ull2a(tmpbuf, va_arg(args, unsigned long long));
|
||||
kputs_pad(tmpbuf, width, pad_char, pad_right);
|
||||
break;
|
||||
case 'o':
|
||||
fmt_o2a(tmpbuf, va_arg(args, unsigned int));
|
||||
kputs_pad(tmpbuf, width, pad_char, pad_right);
|
||||
break;
|
||||
case 's':
|
||||
kputs_pad(va_arg(args, char *),
|
||||
width, pad_char, pad_right);
|
||||
break;
|
||||
case 'u':
|
||||
fmt_u2a(tmpbuf, va_arg(args, unsigned int));
|
||||
kputs_pad(tmpbuf, width, pad_char, pad_right);
|
||||
break;
|
||||
case 'x':
|
||||
fmt_x2a(tmpbuf, va_arg(args, unsigned int));
|
||||
kputs_pad(tmpbuf, width, pad_char, pad_right);
|
||||
break;
|
||||
case 'X':
|
||||
fmt_xl2a(tmpbuf, va_arg(args, unsigned long long));
|
||||
kputs_pad(tmpbuf, width, pad_char, pad_right);
|
||||
break;
|
||||
case '%':
|
||||
kputc('%');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
kputc(*fmt);
|
||||
}
|
||||
if (!*fmt)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kputc(char c)
|
||||
{
|
||||
u16_t * console_memory = (u16_t *) CONSOLE_MEMORY;
|
||||
console_memory += 80 * cursor_y + cursor_x;
|
||||
switch (c)
|
||||
{
|
||||
case '\t':
|
||||
{
|
||||
int to_advance = 8 - (cursor_x & 0x3);
|
||||
while (to_advance--)
|
||||
{
|
||||
*console_memory++ = 0x0720;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '\n':
|
||||
cursor_x = 0;
|
||||
cursor_y++;
|
||||
break;
|
||||
default:
|
||||
*console_memory = 0x0700 | (c & 0xFF);
|
||||
cursor_x++;
|
||||
break;
|
||||
}
|
||||
if (cursor_x >= 80)
|
||||
{
|
||||
cursor_x = 0;
|
||||
cursor_y++;
|
||||
}
|
||||
if (cursor_y >= 25)
|
||||
{
|
||||
memcpy((u8_t *) CONSOLE_MEMORY,
|
||||
(u8_t *) (CONSOLE_MEMORY + 80 * 2),
|
||||
2 * 80 * 24);
|
||||
memsetw((u16_t *) (CONSOLE_MEMORY + 2 * 80 * 24), 0x0720, 80);
|
||||
cursor_y = 24;
|
||||
}
|
||||
writeCursorPosition(cursor_x, cursor_y);
|
||||
}
|
||||
|
||||
void kputs(const char * s)
|
||||
{
|
||||
while (*s)
|
||||
{
|
||||
kputc(*s);
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
void kputs_pad(const char * s, int width, char pad_char, bool pad_right)
|
||||
{
|
||||
int len = strlen(s);
|
||||
if (pad_right)
|
||||
{
|
||||
kputs(s);
|
||||
}
|
||||
int num_pad_chars = width - len;
|
||||
for (int i = 0; i < num_pad_chars; i++)
|
||||
{
|
||||
kputc(pad_char);
|
||||
}
|
||||
if (!pad_right)
|
||||
{
|
||||
kputs(s);
|
||||
}
|
||||
}
|
||||
|
||||
} /* extern "C" */
|
||||
|
||||
static void fmt_d2a(char * buf, int val)
|
||||
{
|
||||
if (val < 0)
|
||||
{
|
||||
*buf++ = '-';
|
||||
val = -val;
|
||||
}
|
||||
fmt_u2a(buf, (unsigned int) val);
|
||||
}
|
||||
|
||||
static void fmt_u2a(char * buf, unsigned int val)
|
||||
{
|
||||
bool printing = false;
|
||||
for (unsigned int div = 1000000000; div >= 1; div /= 10)
|
||||
{
|
||||
unsigned int n = val / div;
|
||||
if (n || div == 1)
|
||||
{
|
||||
printing = true;
|
||||
}
|
||||
if (printing)
|
||||
{
|
||||
*buf++ = '0' + n;
|
||||
}
|
||||
val -= n * div;
|
||||
}
|
||||
*buf = '\0';
|
||||
}
|
||||
|
||||
static void fmt_ll2a(char * buf, long long val)
|
||||
{
|
||||
if (val < 0)
|
||||
{
|
||||
*buf++ = '-';
|
||||
val = -val;
|
||||
}
|
||||
fmt_ull2a(buf, (unsigned long long) val);
|
||||
}
|
||||
|
||||
static void fmt_ull2a(char * buf, unsigned long long val)
|
||||
{
|
||||
bool printing = false;
|
||||
for (unsigned long long div = 10000000000000000000ull; div >= 1; div /= 10)
|
||||
{
|
||||
unsigned long long n = val / div;
|
||||
if (n || div == 1)
|
||||
{
|
||||
printing = true;
|
||||
}
|
||||
if (printing)
|
||||
{
|
||||
*buf++ = '0' + n;
|
||||
}
|
||||
val -= n * div;
|
||||
}
|
||||
*buf = '\0';
|
||||
}
|
||||
|
||||
static void fmt_x2a(char * buf, unsigned int val)
|
||||
{
|
||||
bool printing = false;
|
||||
for (int s = 28; s >= 0; s -= 4)
|
||||
{
|
||||
unsigned int n = (val >> s) & 0xF;
|
||||
if (n || s == 0)
|
||||
{
|
||||
printing = true;
|
||||
}
|
||||
if (printing)
|
||||
{
|
||||
*buf++ = "0123456789abcdef"[n];
|
||||
}
|
||||
}
|
||||
*buf = '\0';
|
||||
}
|
||||
|
||||
static void fmt_xl2a(char * buf, unsigned long long val)
|
||||
{
|
||||
bool printing = false;
|
||||
for (int s = 60; s >= 0; s -= 4)
|
||||
{
|
||||
unsigned int n = (val >> s) & 0xF;
|
||||
if (n || s == 0)
|
||||
{
|
||||
printing = true;
|
||||
}
|
||||
if (printing)
|
||||
{
|
||||
*buf++ = "0123456789abcdef"[n];
|
||||
}
|
||||
}
|
||||
*buf = '\0';
|
||||
}
|
||||
|
||||
static void fmt_o2a(char * buf, unsigned int val)
|
||||
{
|
||||
bool printing = false;
|
||||
for (int s = 30; s >= 0; s -= 3)
|
||||
{
|
||||
unsigned int n = (val >> s) & 0x7;
|
||||
if (n || s == 0)
|
||||
{
|
||||
printing = true;
|
||||
}
|
||||
if (printing)
|
||||
{
|
||||
*buf++ = "01234567"[n];
|
||||
}
|
||||
}
|
||||
*buf = '\0';
|
||||
}
|
||||
|
||||
#include "hos_types.h"
|
||||
#include "hos_defines.h"
|
||||
#include "kio.h"
|
||||
#include "string.h"
|
||||
#include "portio.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdarg.h> /* va_*() */
|
||||
|
||||
static void fmt_d2a(char * buf, int val);
|
||||
static void fmt_u2a(char * buf, unsigned int val);
|
||||
static void fmt_ll2a(char * buf, long long val);
|
||||
static void fmt_ull2a(char * buf, unsigned long long val);
|
||||
static void fmt_x2a(char * buf, unsigned int val);
|
||||
static void fmt_xl2a(char * buf, unsigned long long val);
|
||||
static void fmt_o2a(char * buf, unsigned int val);
|
||||
|
||||
static int cursor_x, cursor_y;
|
||||
|
||||
static void writeCursorPosition(int x, int y)
|
||||
{
|
||||
u16_t pos = 80 * y + x;
|
||||
outportb(0x3D4, 0x0E);
|
||||
outportb(0x3D5, pos >> 8);
|
||||
outportb(0x3D4, 0x0F);
|
||||
outportb(0x3D5, pos);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
void kio_bootstrap()
|
||||
{
|
||||
cursor_x = 0;
|
||||
cursor_y = 9;
|
||||
writeCursorPosition(cursor_x, cursor_y);
|
||||
}
|
||||
|
||||
void kprintf(const char * fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
|
||||
kvprintf(fmt, args);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void kvprintf(const char * fmt, va_list args)
|
||||
{
|
||||
char tmpbuf[25];
|
||||
for ( ; *fmt; fmt++)
|
||||
{
|
||||
if (*fmt == '%')
|
||||
{
|
||||
fmt++;
|
||||
if (*fmt)
|
||||
{
|
||||
int width = 0;
|
||||
char pad_char = ' ';
|
||||
bool pad_right = false;
|
||||
if (*fmt == '0')
|
||||
{
|
||||
pad_char = '0';
|
||||
fmt++;
|
||||
}
|
||||
else if (*fmt == '-')
|
||||
{
|
||||
pad_right = true;
|
||||
fmt++;
|
||||
}
|
||||
for ( ; '0' <= *fmt && *fmt <= '9'; fmt++)
|
||||
{
|
||||
if (width == 0)
|
||||
{
|
||||
width = *fmt - '0';
|
||||
}
|
||||
else
|
||||
{
|
||||
width *= 10;
|
||||
width += *fmt - '0';
|
||||
}
|
||||
}
|
||||
switch (*fmt)
|
||||
{
|
||||
case 'c':
|
||||
kputc(va_arg(args, int));
|
||||
break;
|
||||
case 'd':
|
||||
fmt_d2a(tmpbuf, va_arg(args, int));
|
||||
kputs_pad(tmpbuf, width, pad_char, pad_right);
|
||||
break;
|
||||
case 'l':
|
||||
fmt_ll2a(tmpbuf, va_arg(args, long long));
|
||||
kputs_pad(tmpbuf, width, pad_char, pad_right);
|
||||
break;
|
||||
case 'L':
|
||||
fmt_ull2a(tmpbuf, va_arg(args, unsigned long long));
|
||||
kputs_pad(tmpbuf, width, pad_char, pad_right);
|
||||
break;
|
||||
case 'o':
|
||||
fmt_o2a(tmpbuf, va_arg(args, unsigned int));
|
||||
kputs_pad(tmpbuf, width, pad_char, pad_right);
|
||||
break;
|
||||
case 's':
|
||||
kputs_pad(va_arg(args, char *),
|
||||
width, pad_char, pad_right);
|
||||
break;
|
||||
case 'u':
|
||||
fmt_u2a(tmpbuf, va_arg(args, unsigned int));
|
||||
kputs_pad(tmpbuf, width, pad_char, pad_right);
|
||||
break;
|
||||
case 'x':
|
||||
fmt_x2a(tmpbuf, va_arg(args, unsigned int));
|
||||
kputs_pad(tmpbuf, width, pad_char, pad_right);
|
||||
break;
|
||||
case 'X':
|
||||
fmt_xl2a(tmpbuf, va_arg(args, unsigned long long));
|
||||
kputs_pad(tmpbuf, width, pad_char, pad_right);
|
||||
break;
|
||||
case '%':
|
||||
kputc('%');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
kputc(*fmt);
|
||||
}
|
||||
if (!*fmt)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kputc(char c)
|
||||
{
|
||||
u16_t * console_memory = (u16_t *) CONSOLE_MEMORY;
|
||||
console_memory += 80 * cursor_y + cursor_x;
|
||||
switch (c)
|
||||
{
|
||||
case '\t':
|
||||
{
|
||||
int to_advance = 8 - (cursor_x & 0x3);
|
||||
while (to_advance--)
|
||||
{
|
||||
*console_memory++ = 0x0720;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case '\n':
|
||||
cursor_x = 0;
|
||||
cursor_y++;
|
||||
break;
|
||||
default:
|
||||
*console_memory = 0x0700 | (c & 0xFF);
|
||||
cursor_x++;
|
||||
break;
|
||||
}
|
||||
if (cursor_x >= 80)
|
||||
{
|
||||
cursor_x = 0;
|
||||
cursor_y++;
|
||||
}
|
||||
if (cursor_y >= 25)
|
||||
{
|
||||
memcpy((u8_t *) CONSOLE_MEMORY,
|
||||
(u8_t *) (CONSOLE_MEMORY + 80 * 2),
|
||||
2 * 80 * 24);
|
||||
memsetw((u16_t *) (CONSOLE_MEMORY + 2 * 80 * 24), 0x0720, 80);
|
||||
cursor_y = 24;
|
||||
}
|
||||
writeCursorPosition(cursor_x, cursor_y);
|
||||
}
|
||||
|
||||
void kputs(const char * s)
|
||||
{
|
||||
while (*s)
|
||||
{
|
||||
kputc(*s);
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
void kputs_pad(const char * s, int width, char pad_char, bool pad_right)
|
||||
{
|
||||
int len = strlen(s);
|
||||
if (pad_right)
|
||||
{
|
||||
kputs(s);
|
||||
}
|
||||
int num_pad_chars = width - len;
|
||||
for (int i = 0; i < num_pad_chars; i++)
|
||||
{
|
||||
kputc(pad_char);
|
||||
}
|
||||
if (!pad_right)
|
||||
{
|
||||
kputs(s);
|
||||
}
|
||||
}
|
||||
|
||||
} /* extern "C" */
|
||||
|
||||
static void fmt_d2a(char * buf, int val)
|
||||
{
|
||||
if (val < 0)
|
||||
{
|
||||
*buf++ = '-';
|
||||
val = -val;
|
||||
}
|
||||
fmt_u2a(buf, (unsigned int) val);
|
||||
}
|
||||
|
||||
static void fmt_u2a(char * buf, unsigned int val)
|
||||
{
|
||||
bool printing = false;
|
||||
for (unsigned int div = 1000000000; div >= 1; div /= 10)
|
||||
{
|
||||
unsigned int n = val / div;
|
||||
if (n || div == 1)
|
||||
{
|
||||
printing = true;
|
||||
}
|
||||
if (printing)
|
||||
{
|
||||
*buf++ = '0' + n;
|
||||
}
|
||||
val -= n * div;
|
||||
}
|
||||
*buf = '\0';
|
||||
}
|
||||
|
||||
static void fmt_ll2a(char * buf, long long val)
|
||||
{
|
||||
if (val < 0)
|
||||
{
|
||||
*buf++ = '-';
|
||||
val = -val;
|
||||
}
|
||||
fmt_ull2a(buf, (unsigned long long) val);
|
||||
}
|
||||
|
||||
static void fmt_ull2a(char * buf, unsigned long long val)
|
||||
{
|
||||
bool printing = false;
|
||||
for (unsigned long long div = 10000000000000000000ull; div >= 1; div /= 10)
|
||||
{
|
||||
unsigned long long n = val / div;
|
||||
if (n || div == 1)
|
||||
{
|
||||
printing = true;
|
||||
}
|
||||
if (printing)
|
||||
{
|
||||
*buf++ = '0' + n;
|
||||
}
|
||||
val -= n * div;
|
||||
}
|
||||
*buf = '\0';
|
||||
}
|
||||
|
||||
static void fmt_x2a(char * buf, unsigned int val)
|
||||
{
|
||||
bool printing = false;
|
||||
for (int s = 28; s >= 0; s -= 4)
|
||||
{
|
||||
unsigned int n = (val >> s) & 0xF;
|
||||
if (n || s == 0)
|
||||
{
|
||||
printing = true;
|
||||
}
|
||||
if (printing)
|
||||
{
|
||||
*buf++ = "0123456789abcdef"[n];
|
||||
}
|
||||
}
|
||||
*buf = '\0';
|
||||
}
|
||||
|
||||
static void fmt_xl2a(char * buf, unsigned long long val)
|
||||
{
|
||||
bool printing = false;
|
||||
for (int s = 60; s >= 0; s -= 4)
|
||||
{
|
||||
unsigned int n = (val >> s) & 0xF;
|
||||
if (n || s == 0)
|
||||
{
|
||||
printing = true;
|
||||
}
|
||||
if (printing)
|
||||
{
|
||||
*buf++ = "0123456789abcdef"[n];
|
||||
}
|
||||
}
|
||||
*buf = '\0';
|
||||
}
|
||||
|
||||
static void fmt_o2a(char * buf, unsigned int val)
|
||||
{
|
||||
bool printing = false;
|
||||
for (int s = 30; s >= 0; s -= 3)
|
||||
{
|
||||
unsigned int n = (val >> s) & 0x7;
|
||||
if (n || s == 0)
|
||||
{
|
||||
printing = true;
|
||||
}
|
||||
if (printing)
|
||||
{
|
||||
*buf++ = "01234567"[n];
|
||||
}
|
||||
}
|
||||
*buf = '\0';
|
||||
}
|
||||
|
@ -1,27 +1,27 @@
|
||||
|
||||
#ifndef KIO_H
|
||||
#define KIO_H
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void kio_bootstrap();
|
||||
|
||||
void kprintf(const char * fmt, ...);
|
||||
|
||||
void kvprintf(const char * fmt, va_list args);
|
||||
|
||||
void kputc(char c);
|
||||
|
||||
void kputs(const char * s);
|
||||
|
||||
void kputs_pad(const char * s, int width, char pad_char, bool pad_right);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef KIO_H
|
||||
#define KIO_H
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void kio_bootstrap();
|
||||
|
||||
void kprintf(const char * fmt, ...);
|
||||
|
||||
void kvprintf(const char * fmt, va_list args);
|
||||
|
||||
void kputc(char c);
|
||||
|
||||
void kputs(const char * s);
|
||||
|
||||
void kputs_pad(const char * s, int width, char pad_char, bool pad_right);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -1,73 +1,73 @@
|
||||
|
||||
#include "string.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
void strcpy(char * dst, const char * src)
|
||||
{
|
||||
while (*src)
|
||||
{
|
||||
*dst++ = *src++;
|
||||
}
|
||||
*dst = '\0';
|
||||
}
|
||||
|
||||
u32_t strlen(const char * s)
|
||||
{
|
||||
u32_t len = 0;
|
||||
while (*s++)
|
||||
{
|
||||
len++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
void memcpy(u8_t * dst, u8_t * src, u32_t size)
|
||||
{
|
||||
for (u32_t n = 0; n < size; n++)
|
||||
{
|
||||
*dst++ = *src++;
|
||||
}
|
||||
}
|
||||
|
||||
void memcpyw(u16_t * dst, u16_t * src, u32_t size)
|
||||
{
|
||||
for (u32_t n = 0; n < size; n++)
|
||||
{
|
||||
*dst++ = *src++;
|
||||
}
|
||||
}
|
||||
|
||||
void memcpyd(u32_t * dst, u32_t * src, u32_t size)
|
||||
{
|
||||
for (u32_t n = 0; n < size; n++)
|
||||
{
|
||||
*dst++ = *src++;
|
||||
}
|
||||
}
|
||||
|
||||
void memset(u8_t * dst, u8_t val, u32_t size)
|
||||
{
|
||||
for (u32_t n = 0; n < size; n++)
|
||||
{
|
||||
*dst++ = val;
|
||||
}
|
||||
}
|
||||
|
||||
void memsetw(u16_t * dst, u16_t val, u32_t size)
|
||||
{
|
||||
for (u32_t n = 0; n < size; n++)
|
||||
{
|
||||
*dst++ = val;
|
||||
}
|
||||
}
|
||||
|
||||
void memsetd(u32_t * dst, u32_t val, u32_t size)
|
||||
{
|
||||
for (u32_t n = 0; n < size; n++)
|
||||
{
|
||||
*dst++ = val;
|
||||
}
|
||||
}
|
||||
|
||||
} /* extern "C" */
|
||||
|
||||
#include "string.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
void strcpy(char * dst, const char * src)
|
||||
{
|
||||
while (*src)
|
||||
{
|
||||
*dst++ = *src++;
|
||||
}
|
||||
*dst = '\0';
|
||||
}
|
||||
|
||||
u32_t strlen(const char * s)
|
||||
{
|
||||
u32_t len = 0;
|
||||
while (*s++)
|
||||
{
|
||||
len++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
void memcpy(u8_t * dst, u8_t * src, u32_t size)
|
||||
{
|
||||
for (u32_t n = 0; n < size; n++)
|
||||
{
|
||||
*dst++ = *src++;
|
||||
}
|
||||
}
|
||||
|
||||
void memcpyw(u16_t * dst, u16_t * src, u32_t size)
|
||||
{
|
||||
for (u32_t n = 0; n < size; n++)
|
||||
{
|
||||
*dst++ = *src++;
|
||||
}
|
||||
}
|
||||
|
||||
void memcpyd(u32_t * dst, u32_t * src, u32_t size)
|
||||
{
|
||||
for (u32_t n = 0; n < size; n++)
|
||||
{
|
||||
*dst++ = *src++;
|
||||
}
|
||||
}
|
||||
|
||||
void memset(u8_t * dst, u8_t val, u32_t size)
|
||||
{
|
||||
for (u32_t n = 0; n < size; n++)
|
||||
{
|
||||
*dst++ = val;
|
||||
}
|
||||
}
|
||||
|
||||
void memsetw(u16_t * dst, u16_t val, u32_t size)
|
||||
{
|
||||
for (u32_t n = 0; n < size; n++)
|
||||
{
|
||||
*dst++ = val;
|
||||
}
|
||||
}
|
||||
|
||||
void memsetd(u32_t * dst, u32_t val, u32_t size)
|
||||
{
|
||||
for (u32_t n = 0; n < size; n++)
|
||||
{
|
||||
*dst++ = val;
|
||||
}
|
||||
}
|
||||
|
||||
} /* extern "C" */
|
||||
|
@ -1,27 +1,27 @@
|
||||
|
||||
#ifndef STRING_H
|
||||
#define STRING_H
|
||||
|
||||
#include "hos_defines.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void strcpy(char * dst, const char * src);
|
||||
|
||||
u32_t strlen(const char * s);
|
||||
|
||||
void memcpy(u8_t * dst, u8_t * src, u32_t size);
|
||||
void memcpyw(u16_t * dst, u16_t * src, u32_t size);
|
||||
void memcpyd(u32_t * dst, u32_t * src, u32_t size);
|
||||
|
||||
void memset(u8_t * dst, u8_t val, u32_t size);
|
||||
void memsetw(u16_t * dst, u16_t val, u32_t size);
|
||||
void memsetd(u32_t * dst, u32_t val, u32_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef STRING_H
|
||||
#define STRING_H
|
||||
|
||||
#include "hos_defines.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void strcpy(char * dst, const char * src);
|
||||
|
||||
u32_t strlen(const char * s);
|
||||
|
||||
void memcpy(u8_t * dst, u8_t * src, u32_t size);
|
||||
void memcpyw(u16_t * dst, u16_t * src, u32_t size);
|
||||
void memcpyd(u32_t * dst, u32_t * src, u32_t size);
|
||||
|
||||
void memset(u8_t * dst, u8_t val, u32_t size);
|
||||
void memsetw(u16_t * dst, u16_t val, u32_t size);
|
||||
void memsetd(u32_t * dst, u32_t val, u32_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -1,34 +1,34 @@
|
||||
OUTPUT_FORMAT(elf32-i386)
|
||||
ENTRY(start)
|
||||
virt = 0x00100000;
|
||||
phys = 0x00100000;
|
||||
SECTIONS
|
||||
{
|
||||
.text virt : AT(phys) {
|
||||
code = .; _code = .; __code = .;
|
||||
*(.multiboot_header*)
|
||||
*(.text*)
|
||||
*(.gnu.linkonce*)
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
.rodata : {
|
||||
*(.rodata*)
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
.other : {
|
||||
*(.eh_*)
|
||||
*(.rel*)
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
.data : {
|
||||
data = .; _data = .; __data = .;
|
||||
*(.data*)
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
.bss : {
|
||||
bss = .; _bss = .; __bss = .;
|
||||
*(.bss*)
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
end = .; _end = .; __end = .;
|
||||
}
|
||||
OUTPUT_FORMAT(elf32-i386)
|
||||
ENTRY(start)
|
||||
virt = 0x00100000;
|
||||
phys = 0x00100000;
|
||||
SECTIONS
|
||||
{
|
||||
.text virt : AT(phys) {
|
||||
code = .; _code = .; __code = .;
|
||||
*(.multiboot_header*)
|
||||
*(.text*)
|
||||
*(.gnu.linkonce*)
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
.rodata : {
|
||||
*(.rodata*)
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
.other : {
|
||||
*(.eh_*)
|
||||
*(.rel*)
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
.data : {
|
||||
data = .; _data = .; __data = .;
|
||||
*(.data*)
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
.bss : {
|
||||
bss = .; _bss = .; __bss = .;
|
||||
*(.bss*)
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
end = .; _end = .; __end = .;
|
||||
}
|
||||
|
640
kernel/mm/mm.cc
640
kernel/mm/mm.cc
@ -1,320 +1,320 @@
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "mm.h"
|
||||
#include "stack.h"
|
||||
#include "boot/k_early_panic.h"
|
||||
#include "lang/string.h"
|
||||
#include "lang/kio.h"
|
||||
#include "sys/cpu.h"
|
||||
|
||||
#define MM_MAX_MMAP_ENTRIES 64
|
||||
|
||||
static pagedirectory_entry_t * page_directory;
|
||||
static mm_mem_range_t mm_mmap_entries[MM_MAX_MMAP_ENTRIES];
|
||||
static int mm_mmap_num_entries = 0;
|
||||
static int mm_num_free_pages = 0;
|
||||
static int mm_num_total_pages = 0;
|
||||
gdtr_t mm_gdtr;
|
||||
static u64_t * mm_gdt;
|
||||
static u32_t mm_heap_base;
|
||||
|
||||
/* physical addresses of page allocation pages to map in before the heap */
|
||||
static u32_t page_alloc_page_numbers[1025]; /* supports 4GB physical memory */
|
||||
static u32_t num_page_alloc_pages = 0;
|
||||
static mm_page_alloc_page_t * current_page_alloc_page = NULL;
|
||||
static u32_t page_alloc_page_index = 0;
|
||||
static mm_page_alloc_page_t * page_alloc_pages;
|
||||
|
||||
/**************************************************************************
|
||||
* Internal Functions *
|
||||
*************************************************************************/
|
||||
static void record_phys_page(u32_t base_address);
|
||||
|
||||
/**************************************************************************
|
||||
* This function is run in segmented memory before paging is in effect. *
|
||||
*************************************************************************/
|
||||
void mm_record_mmap_entry(mb_mmap_t * mmap)
|
||||
{
|
||||
if (mm_mmap_num_entries < MM_MAX_MMAP_ENTRIES)
|
||||
{
|
||||
if (mmap->type == MB_MMAP_TYPE_RAM)
|
||||
{
|
||||
mm_mmap_entries[mm_mmap_num_entries].base = mmap->base;
|
||||
mm_mmap_entries[mm_mmap_num_entries].length = mmap->length;
|
||||
mm_mmap_num_entries++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
k_early_panic("Too many mmap_entries!");
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* This function is run in segmented memory before paging is in effect. *
|
||||
* It is run after the bootloader information has been read, so we can *
|
||||
* overwrite that memory now. *
|
||||
*************************************************************************/
|
||||
void mm_bootstrap()
|
||||
{
|
||||
u32_t max_ram_address = KERNEL_PHYSICAL_ADDRESS + KERNEL_SIZE - 1;
|
||||
/* this function requires a big enough initial stack to run */
|
||||
BUILD_BUG_ON((STACK_INITIAL_SIZE * PAGE_SIZE) < 8000);
|
||||
|
||||
/* check that a mm_page_alloc_page_t fits exactly in a page */
|
||||
BUILD_BUG_ON(sizeof(mm_page_alloc_page_t) != PAGE_SIZE);
|
||||
|
||||
if (mm_mmap_num_entries < 1)
|
||||
{
|
||||
k_early_panic("No mmap entries read from bootloader!");
|
||||
}
|
||||
|
||||
mm_heap_base = (u32_t) KERNEL_END;
|
||||
page_alloc_pages = (mm_page_alloc_page_t *) mm_heap_base;
|
||||
|
||||
for (int mmap_idx = 0; mmap_idx < mm_mmap_num_entries; mmap_idx++)
|
||||
{
|
||||
u32_t base_address = mm_mmap_entries[mmap_idx].base;
|
||||
u32_t address_limit = base_address + mm_mmap_entries[mmap_idx].length;
|
||||
|
||||
if (base_address & PAGE_LOW_MASK)
|
||||
{
|
||||
/* start of this mmap range is not page-aligned */
|
||||
base_address = (base_address & PAGE_HIGH_MASK) + PAGE_SIZE;
|
||||
}
|
||||
if (address_limit & PAGE_LOW_MASK)
|
||||
{
|
||||
/* end of this mmap range is not page-aligned */
|
||||
address_limit &= PAGE_HIGH_MASK;
|
||||
}
|
||||
|
||||
/* record the highest RAM address found */
|
||||
if ((address_limit - 1) > max_ram_address)
|
||||
{
|
||||
max_ram_address = (address_limit - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* loop through every page in the mmap range and add
|
||||
* pages into the free page linked list
|
||||
*/
|
||||
for (; base_address < address_limit; base_address += PAGE_SIZE)
|
||||
{
|
||||
/* check to make sure the page doesn't overlap the kernel */
|
||||
if ( base_address + PAGE_SIZE <= KERNEL_PHYSICAL_ADDRESS
|
||||
|| base_address >= KERNEL_PHYSICAL_ADDRESS + KERNEL_SIZE )
|
||||
{
|
||||
record_phys_page(base_address);
|
||||
mm_num_free_pages++;
|
||||
}
|
||||
mm_num_total_pages++;
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < num_page_alloc_pages; i++)
|
||||
{
|
||||
mm_early_map(mm_heap_base, page_alloc_page_numbers[i], 0, 1);
|
||||
current_page_alloc_page = (mm_page_alloc_page_t *) mm_heap_base;
|
||||
/* move the heap back to after the page allocation pages */
|
||||
mm_heap_base += PAGE_SIZE;
|
||||
}
|
||||
|
||||
if (mm_num_free_pages < 10)
|
||||
{
|
||||
k_early_panic("Not enough free pages of RAM!");
|
||||
}
|
||||
|
||||
/* ok, now mm_page_alloc() should be functional */
|
||||
|
||||
/* allocate the page directory */
|
||||
u32_t page_directory_phys = mm_page_alloc();
|
||||
page_directory = (pagedirectory_entry_t *) page_directory_phys;
|
||||
pagedirectory_entry_t * page_dir_virt =
|
||||
(pagedirectory_entry_t *) (page_directory_phys + KERNEL_OFFSET);
|
||||
|
||||
/* Clear the page directory */
|
||||
for (unsigned int i = 0; i < NUM_PAGETABLE_ENTRIES; i++)
|
||||
{
|
||||
page_dir_virt[i] = 0;
|
||||
}
|
||||
|
||||
/* now map the kernel's virtual address space into RAM */
|
||||
for (u32_t page_base = KERNEL_VIRTUAL_ADDRESS;
|
||||
page_base < KERNEL_VIRTUAL_ADDRESS + KERNEL_SIZE;
|
||||
page_base += PAGE_SIZE)
|
||||
{
|
||||
/* map page_base to page_base - KERNEL_OFFSET */
|
||||
mm_early_map(page_base, page_base - KERNEL_OFFSET, 0, 1);
|
||||
}
|
||||
|
||||
/* set up the global descriptor table */
|
||||
u32_t gdt_base = mm_page_alloc();
|
||||
mm_gdt = (u64_t *) ((u32_t) gdt_base + (u32_t) KERNEL_OFFSET);
|
||||
mm_gdt[0] = 0x0ull;
|
||||
mm_gdt[1] = MAKE_DESCRIPTOR(0, 0xFFFFF, 1, 0, 1, 1); /* kernel code */
|
||||
mm_gdt[2] = MAKE_DESCRIPTOR(0, 0xFFFFF, 1, 0, 1, 0); /* kernel data */
|
||||
mm_gdtr.limit = 3 * sizeof(mm_gdt[0]) - 1;
|
||||
mm_gdtr.base = gdt_base;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
"lgdt (mm_gdtr);\n"
|
||||
"jmp $0x08, $42f;\n"
|
||||
"42:\n"
|
||||
"mov $0x10, %%cx\n"
|
||||
"mov %%cx, %%ss\n"
|
||||
"mov %%cx, %%ds\n"
|
||||
"mov %%cx, %%es\n"
|
||||
"mov %%cx, %%fs\n"
|
||||
"mov %%cx, %%gs\n"
|
||||
: /* no outputs */
|
||||
: /* no inputs */
|
||||
: "ecx");
|
||||
|
||||
/* set the page directory base register */
|
||||
write_cr3(page_directory);
|
||||
|
||||
/* turn on paging */
|
||||
write_cr0(read_cr0() | (1 << 31));
|
||||
|
||||
stack_bootstrap();
|
||||
}
|
||||
|
||||
static void record_phys_page(u32_t base_address)
|
||||
{
|
||||
if (page_alloc_page_index == 0)
|
||||
{
|
||||
/* allocate a new page alloc page */
|
||||
mm_page_alloc_page_t * old_page_alloc_page = current_page_alloc_page;
|
||||
current_page_alloc_page = (mm_page_alloc_page_t *)
|
||||
(base_address + KERNEL_OFFSET);
|
||||
current_page_alloc_page->next = old_page_alloc_page;
|
||||
page_alloc_page_index =
|
||||
sizeof(current_page_alloc_page->pages)
|
||||
/ sizeof(current_page_alloc_page->pages[0]) - 1;
|
||||
page_alloc_page_numbers[num_page_alloc_pages++] = base_address;
|
||||
}
|
||||
else
|
||||
{
|
||||
current_page_alloc_page->pages[page_alloc_page_index--] = base_address;
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* Map virtual_address to physical_address. *
|
||||
* Both addresses should be page-aligned. *
|
||||
* This 'early' version can be used during segmented bootstrapping *
|
||||
*************************************************************************/
|
||||
int mm_early_map(u32_t virtual_address, u32_t physical_address,
|
||||
u32_t user_mode, u32_t writable)
|
||||
{
|
||||
u32_t directory_index = (virtual_address >> 22) & 0x3FF;
|
||||
u32_t table_index = (virtual_address >> 12) & 0x3FF;
|
||||
pagedirectory_entry_t * page_dir = page_directory;
|
||||
page_dir = (pagedirectory_entry_t *)((u32_t)page_dir + KERNEL_OFFSET);
|
||||
|
||||
if (page_dir[directory_index] == 0)
|
||||
{
|
||||
/* allocate a new page table */
|
||||
u32_t page_table_address = mm_page_alloc();
|
||||
if (page_table_address == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
page_dir[directory_index] = page_table_address
|
||||
| 0x1 << 2 /* PTs can be user mode */
|
||||
| 0x1 << 1 /* writable */
|
||||
| 0x1; /* present */
|
||||
}
|
||||
u32_t page_table_address = page_dir[directory_index] & PAGE_HIGH_MASK;
|
||||
|
||||
u32_t * page_table = (u32_t *) page_table_address;
|
||||
page_table = (u32_t *)((u32_t)page_table + (u32_t)KERNEL_OFFSET);
|
||||
|
||||
page_table[table_index] = (physical_address & PAGE_HIGH_MASK)
|
||||
| (user_mode & 0x1) << 2
|
||||
| (writable & 0x1) << 1
|
||||
| 0x1; /* present */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* Map virtual_address to physical_address. *
|
||||
* Both addresses should be page-aligned. *
|
||||
*************************************************************************/
|
||||
int mm_map(u32_t virtual_address, u32_t physical_address,
|
||||
u32_t user_mode, u32_t writable)
|
||||
{
|
||||
u32_t directory_index = (virtual_address >> 22) & 0x3FF;
|
||||
u32_t table_index = (virtual_address >> 12) & 0x3FF;
|
||||
pagedirectory_entry_t * page_dir = page_directory;
|
||||
|
||||
if (page_dir[directory_index] == 0)
|
||||
{
|
||||
/* allocate a new page table */
|
||||
u32_t page_table_address = mm_page_alloc();
|
||||
if (page_table_address == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
page_dir[directory_index] = page_table_address
|
||||
| 0x1 << 2 /* PTs can be user mode */
|
||||
| 0x1 << 1 /* writable */
|
||||
| 0x1; /* present */
|
||||
}
|
||||
u32_t page_table_address = page_dir[directory_index] & PAGE_HIGH_MASK;
|
||||
|
||||
u32_t * page_table = (u32_t *) page_table_address;
|
||||
|
||||
page_table[table_index] = (physical_address & PAGE_HIGH_MASK)
|
||||
| (user_mode & 0x1) << 2
|
||||
| (writable & 0x1) << 1
|
||||
| 0x1; /* present */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* Returns the physical base address of a page in RAM *
|
||||
* or 0 if no pages were available *
|
||||
*************************************************************************/
|
||||
u32_t mm_page_alloc()
|
||||
{
|
||||
u32_t page_address = 0;
|
||||
if (current_page_alloc_page != NULL)
|
||||
{
|
||||
if (page_alloc_page_index == sizeof(current_page_alloc_page->pages)
|
||||
/ sizeof(current_page_alloc_page->pages[0]) - 1)
|
||||
{
|
||||
page_address = ((u32_t) current_page_alloc_page) - KERNEL_OFFSET;
|
||||
current_page_alloc_page = current_page_alloc_page->next;
|
||||
page_alloc_page_index = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
page_alloc_page_index++;
|
||||
page_address =
|
||||
current_page_alloc_page->pages[page_alloc_page_index];
|
||||
}
|
||||
mm_num_free_pages--;
|
||||
}
|
||||
return page_address;
|
||||
}
|
||||
|
||||
void mm_print_memory_map()
|
||||
{
|
||||
kprintf("Bootloader provided memory map:\n");
|
||||
kprintf(" Base Address Length\n");
|
||||
for (int i = 0; i < mm_mmap_num_entries; i++)
|
||||
{
|
||||
kprintf(" 0x%016X 0x%016X (%l bytes / %l KB / %l MB)\n",
|
||||
mm_mmap_entries[i].base,
|
||||
mm_mmap_entries[i].length,
|
||||
mm_mmap_entries[i].length,
|
||||
mm_mmap_entries[i].length >> 10,
|
||||
mm_mmap_entries[i].length >> 20);
|
||||
}
|
||||
kprintf("Used pages: %d\n", mm_num_total_pages - mm_num_free_pages);
|
||||
kprintf("Free pages: %d\n", mm_num_free_pages);
|
||||
}
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "mm.h"
|
||||
#include "stack.h"
|
||||
#include "boot/k_early_panic.h"
|
||||
#include "lang/string.h"
|
||||
#include "lang/kio.h"
|
||||
#include "sys/cpu.h"
|
||||
|
||||
#define MM_MAX_MMAP_ENTRIES 64
|
||||
|
||||
static pagedirectory_entry_t * page_directory;
|
||||
static mm_mem_range_t mm_mmap_entries[MM_MAX_MMAP_ENTRIES];
|
||||
static int mm_mmap_num_entries = 0;
|
||||
static int mm_num_free_pages = 0;
|
||||
static int mm_num_total_pages = 0;
|
||||
gdtr_t mm_gdtr;
|
||||
static u64_t * mm_gdt;
|
||||
static u32_t mm_heap_base;
|
||||
|
||||
/* physical addresses of page allocation pages to map in before the heap */
|
||||
static u32_t page_alloc_page_numbers[1025]; /* supports 4GB physical memory */
|
||||
static u32_t num_page_alloc_pages = 0;
|
||||
static mm_page_alloc_page_t * current_page_alloc_page = NULL;
|
||||
static u32_t page_alloc_page_index = 0;
|
||||
static mm_page_alloc_page_t * page_alloc_pages;
|
||||
|
||||
/**************************************************************************
|
||||
* Internal Functions *
|
||||
*************************************************************************/
|
||||
static void record_phys_page(u32_t base_address);
|
||||
|
||||
/**************************************************************************
|
||||
* This function is run in segmented memory before paging is in effect. *
|
||||
*************************************************************************/
|
||||
void mm_record_mmap_entry(mb_mmap_t * mmap)
|
||||
{
|
||||
if (mm_mmap_num_entries < MM_MAX_MMAP_ENTRIES)
|
||||
{
|
||||
if (mmap->type == MB_MMAP_TYPE_RAM)
|
||||
{
|
||||
mm_mmap_entries[mm_mmap_num_entries].base = mmap->base;
|
||||
mm_mmap_entries[mm_mmap_num_entries].length = mmap->length;
|
||||
mm_mmap_num_entries++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
k_early_panic("Too many mmap_entries!");
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* This function is run in segmented memory before paging is in effect. *
|
||||
* It is run after the bootloader information has been read, so we can *
|
||||
* overwrite that memory now. *
|
||||
*************************************************************************/
|
||||
void mm_bootstrap()
|
||||
{
|
||||
u32_t max_ram_address = KERNEL_PHYSICAL_ADDRESS + KERNEL_SIZE - 1;
|
||||
/* this function requires a big enough initial stack to run */
|
||||
BUILD_BUG_ON((STACK_INITIAL_SIZE * PAGE_SIZE) < 8000);
|
||||
|
||||
/* check that a mm_page_alloc_page_t fits exactly in a page */
|
||||
BUILD_BUG_ON(sizeof(mm_page_alloc_page_t) != PAGE_SIZE);
|
||||
|
||||
if (mm_mmap_num_entries < 1)
|
||||
{
|
||||
k_early_panic("No mmap entries read from bootloader!");
|
||||
}
|
||||
|
||||
mm_heap_base = (u32_t) KERNEL_END;
|
||||
page_alloc_pages = (mm_page_alloc_page_t *) mm_heap_base;
|
||||
|
||||
for (int mmap_idx = 0; mmap_idx < mm_mmap_num_entries; mmap_idx++)
|
||||
{
|
||||
u32_t base_address = mm_mmap_entries[mmap_idx].base;
|
||||
u32_t address_limit = base_address + mm_mmap_entries[mmap_idx].length;
|
||||
|
||||
if (base_address & PAGE_LOW_MASK)
|
||||
{
|
||||
/* start of this mmap range is not page-aligned */
|
||||
base_address = (base_address & PAGE_HIGH_MASK) + PAGE_SIZE;
|
||||
}
|
||||
if (address_limit & PAGE_LOW_MASK)
|
||||
{
|
||||
/* end of this mmap range is not page-aligned */
|
||||
address_limit &= PAGE_HIGH_MASK;
|
||||
}
|
||||
|
||||
/* record the highest RAM address found */
|
||||
if ((address_limit - 1) > max_ram_address)
|
||||
{
|
||||
max_ram_address = (address_limit - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* loop through every page in the mmap range and add
|
||||
* pages into the free page linked list
|
||||
*/
|
||||
for (; base_address < address_limit; base_address += PAGE_SIZE)
|
||||
{
|
||||
/* check to make sure the page doesn't overlap the kernel */
|
||||
if ( base_address + PAGE_SIZE <= KERNEL_PHYSICAL_ADDRESS
|
||||
|| base_address >= KERNEL_PHYSICAL_ADDRESS + KERNEL_SIZE )
|
||||
{
|
||||
record_phys_page(base_address);
|
||||
mm_num_free_pages++;
|
||||
}
|
||||
mm_num_total_pages++;
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < num_page_alloc_pages; i++)
|
||||
{
|
||||
mm_early_map(mm_heap_base, page_alloc_page_numbers[i], 0, 1);
|
||||
current_page_alloc_page = (mm_page_alloc_page_t *) mm_heap_base;
|
||||
/* move the heap back to after the page allocation pages */
|
||||
mm_heap_base += PAGE_SIZE;
|
||||
}
|
||||
|
||||
if (mm_num_free_pages < 10)
|
||||
{
|
||||
k_early_panic("Not enough free pages of RAM!");
|
||||
}
|
||||
|
||||
/* ok, now mm_page_alloc() should be functional */
|
||||
|
||||
/* allocate the page directory */
|
||||
u32_t page_directory_phys = mm_page_alloc();
|
||||
page_directory = (pagedirectory_entry_t *) page_directory_phys;
|
||||
pagedirectory_entry_t * page_dir_virt =
|
||||
(pagedirectory_entry_t *) (page_directory_phys + KERNEL_OFFSET);
|
||||
|
||||
/* Clear the page directory */
|
||||
for (unsigned int i = 0; i < NUM_PAGETABLE_ENTRIES; i++)
|
||||
{
|
||||
page_dir_virt[i] = 0;
|
||||
}
|
||||
|
||||
/* now map the kernel's virtual address space into RAM */
|
||||
for (u32_t page_base = KERNEL_VIRTUAL_ADDRESS;
|
||||
page_base < KERNEL_VIRTUAL_ADDRESS + KERNEL_SIZE;
|
||||
page_base += PAGE_SIZE)
|
||||
{
|
||||
/* map page_base to page_base - KERNEL_OFFSET */
|
||||
mm_early_map(page_base, page_base - KERNEL_OFFSET, 0, 1);
|
||||
}
|
||||
|
||||
/* set up the global descriptor table */
|
||||
u32_t gdt_base = mm_page_alloc();
|
||||
mm_gdt = (u64_t *) ((u32_t) gdt_base + (u32_t) KERNEL_OFFSET);
|
||||
mm_gdt[0] = 0x0ull;
|
||||
mm_gdt[1] = MAKE_DESCRIPTOR(0, 0xFFFFF, 1, 0, 1, 1); /* kernel code */
|
||||
mm_gdt[2] = MAKE_DESCRIPTOR(0, 0xFFFFF, 1, 0, 1, 0); /* kernel data */
|
||||
mm_gdtr.limit = 3 * sizeof(mm_gdt[0]) - 1;
|
||||
mm_gdtr.base = gdt_base;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
"lgdt (mm_gdtr);\n"
|
||||
"jmp $0x08, $42f;\n"
|
||||
"42:\n"
|
||||
"mov $0x10, %%cx\n"
|
||||
"mov %%cx, %%ss\n"
|
||||
"mov %%cx, %%ds\n"
|
||||
"mov %%cx, %%es\n"
|
||||
"mov %%cx, %%fs\n"
|
||||
"mov %%cx, %%gs\n"
|
||||
: /* no outputs */
|
||||
: /* no inputs */
|
||||
: "ecx");
|
||||
|
||||
/* set the page directory base register */
|
||||
write_cr3(page_directory);
|
||||
|
||||
/* turn on paging */
|
||||
write_cr0(read_cr0() | (1 << 31));
|
||||
|
||||
stack_bootstrap();
|
||||
}
|
||||
|
||||
static void record_phys_page(u32_t base_address)
|
||||
{
|
||||
if (page_alloc_page_index == 0)
|
||||
{
|
||||
/* allocate a new page alloc page */
|
||||
mm_page_alloc_page_t * old_page_alloc_page = current_page_alloc_page;
|
||||
current_page_alloc_page = (mm_page_alloc_page_t *)
|
||||
(base_address + KERNEL_OFFSET);
|
||||
current_page_alloc_page->next = old_page_alloc_page;
|
||||
page_alloc_page_index =
|
||||
sizeof(current_page_alloc_page->pages)
|
||||
/ sizeof(current_page_alloc_page->pages[0]) - 1;
|
||||
page_alloc_page_numbers[num_page_alloc_pages++] = base_address;
|
||||
}
|
||||
else
|
||||
{
|
||||
current_page_alloc_page->pages[page_alloc_page_index--] = base_address;
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* Map virtual_address to physical_address. *
|
||||
* Both addresses should be page-aligned. *
|
||||
* This 'early' version can be used during segmented bootstrapping *
|
||||
*************************************************************************/
|
||||
int mm_early_map(u32_t virtual_address, u32_t physical_address,
|
||||
u32_t user_mode, u32_t writable)
|
||||
{
|
||||
u32_t directory_index = (virtual_address >> 22) & 0x3FF;
|
||||
u32_t table_index = (virtual_address >> 12) & 0x3FF;
|
||||
pagedirectory_entry_t * page_dir = page_directory;
|
||||
page_dir = (pagedirectory_entry_t *)((u32_t)page_dir + KERNEL_OFFSET);
|
||||
|
||||
if (page_dir[directory_index] == 0)
|
||||
{
|
||||
/* allocate a new page table */
|
||||
u32_t page_table_address = mm_page_alloc();
|
||||
if (page_table_address == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
page_dir[directory_index] = page_table_address
|
||||
| 0x1 << 2 /* PTs can be user mode */
|
||||
| 0x1 << 1 /* writable */
|
||||
| 0x1; /* present */
|
||||
}
|
||||
u32_t page_table_address = page_dir[directory_index] & PAGE_HIGH_MASK;
|
||||
|
||||
u32_t * page_table = (u32_t *) page_table_address;
|
||||
page_table = (u32_t *)((u32_t)page_table + (u32_t)KERNEL_OFFSET);
|
||||
|
||||
page_table[table_index] = (physical_address & PAGE_HIGH_MASK)
|
||||
| (user_mode & 0x1) << 2
|
||||
| (writable & 0x1) << 1
|
||||
| 0x1; /* present */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* Map virtual_address to physical_address. *
|
||||
* Both addresses should be page-aligned. *
|
||||
*************************************************************************/
|
||||
int mm_map(u32_t virtual_address, u32_t physical_address,
|
||||
u32_t user_mode, u32_t writable)
|
||||
{
|
||||
u32_t directory_index = (virtual_address >> 22) & 0x3FF;
|
||||
u32_t table_index = (virtual_address >> 12) & 0x3FF;
|
||||
pagedirectory_entry_t * page_dir = page_directory;
|
||||
|
||||
if (page_dir[directory_index] == 0)
|
||||
{
|
||||
/* allocate a new page table */
|
||||
u32_t page_table_address = mm_page_alloc();
|
||||
if (page_table_address == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
page_dir[directory_index] = page_table_address
|
||||
| 0x1 << 2 /* PTs can be user mode */
|
||||
| 0x1 << 1 /* writable */
|
||||
| 0x1; /* present */
|
||||
}
|
||||
u32_t page_table_address = page_dir[directory_index] & PAGE_HIGH_MASK;
|
||||
|
||||
u32_t * page_table = (u32_t *) page_table_address;
|
||||
|
||||
page_table[table_index] = (physical_address & PAGE_HIGH_MASK)
|
||||
| (user_mode & 0x1) << 2
|
||||
| (writable & 0x1) << 1
|
||||
| 0x1; /* present */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* Returns the physical base address of a page in RAM *
|
||||
* or 0 if no pages were available *
|
||||
*************************************************************************/
|
||||
u32_t mm_page_alloc()
|
||||
{
|
||||
u32_t page_address = 0;
|
||||
if (current_page_alloc_page != NULL)
|
||||
{
|
||||
if (page_alloc_page_index == sizeof(current_page_alloc_page->pages)
|
||||
/ sizeof(current_page_alloc_page->pages[0]) - 1)
|
||||
{
|
||||
page_address = ((u32_t) current_page_alloc_page) - KERNEL_OFFSET;
|
||||
current_page_alloc_page = current_page_alloc_page->next;
|
||||
page_alloc_page_index = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
page_alloc_page_index++;
|
||||
page_address =
|
||||
current_page_alloc_page->pages[page_alloc_page_index];
|
||||
}
|
||||
mm_num_free_pages--;
|
||||
}
|
||||
return page_address;
|
||||
}
|
||||
|
||||
void mm_print_memory_map()
|
||||
{
|
||||
kprintf("Bootloader provided memory map:\n");
|
||||
kprintf(" Base Address Length\n");
|
||||
for (int i = 0; i < mm_mmap_num_entries; i++)
|
||||
{
|
||||
kprintf(" 0x%016X 0x%016X (%l bytes / %l KB / %l MB)\n",
|
||||
mm_mmap_entries[i].base,
|
||||
mm_mmap_entries[i].length,
|
||||
mm_mmap_entries[i].length,
|
||||
mm_mmap_entries[i].length >> 10,
|
||||
mm_mmap_entries[i].length >> 20);
|
||||
}
|
||||
kprintf("Used pages: %d\n", mm_num_total_pages - mm_num_free_pages);
|
||||
kprintf("Free pages: %d\n", mm_num_free_pages);
|
||||
}
|
||||
|
128
kernel/mm/mm.h
128
kernel/mm/mm.h
@ -1,64 +1,64 @@
|
||||
|
||||
#ifndef MM_H
|
||||
#define MM_H MM_H
|
||||
|
||||
#include "hos_types.h"
|
||||
#include "hos_defines.h"
|
||||
#include "multiboot.h"
|
||||
|
||||
#define KERNEL_CODE_SEGMENT 0x08
|
||||
#define KERNEL_DATA_SEGMENT 0x10
|
||||
|
||||
typedef u32_t pagedirectory_entry_t;
|
||||
|
||||
#define NUM_PAGETABLE_ENTRIES (PAGE_SIZE / sizeof(pagedirectory_entry_t))
|
||||
|
||||
typedef pagedirectory_entry_t pagedirectory_t[NUM_PAGETABLE_ENTRIES];
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u64_t base;
|
||||
u64_t length;
|
||||
} mm_mem_range_t;
|
||||
|
||||
typedef struct mm_page_alloc_page_s
|
||||
{
|
||||
u32_t pages[PAGE_SIZE / sizeof(u32_t) - 1];
|
||||
mm_page_alloc_page_s * next;
|
||||
} mm_page_alloc_page_t;
|
||||
|
||||
/* http://courses.ece.illinois.edu/ece391/references/descriptors.pdf */
|
||||
/* granularity: 0: limit in bytes; 1: limit in pages */
|
||||
/* dpl: 0: system mode; 3: user mode */
|
||||
/* normal: 0: TSS/LDT/call gate; 1: code/data segment */
|
||||
/* code_seg: 0: data segment; 1: code segment */
|
||||
#define MAKE_DESCRIPTOR(base, limit, granularity, dpl, normal, code_seg) \
|
||||
(u64_t) ( ( (((u64_t) base) & 0xFF000000ull) << 32 ) /* base 31:24 */ \
|
||||
| ( (((u64_t) granularity) & 0x1ull) << 55 ) /* granularity */ \
|
||||
| ( ( (u64_t) 0x1ull) << 54 ) /* 32-bit */ \
|
||||
| ( (((u64_t) limit) & 0xF0000ull) << 32 ) /* limit 19:16 */ \
|
||||
| ( ( (u64_t) 0x1ull) << 47 ) /* present */ \
|
||||
| ( (((u64_t) dpl) & 0x3ull) << 45 ) /* dpl */ \
|
||||
| ( (((u64_t) normal) & 0x1ull) << 44 ) /* normal */ \
|
||||
| ( (((u64_t) code_seg) & 0x1ull) << 43 ) /* code seg */ \
|
||||
| ( ( (u64_t) 0x2ull) << 40 ) /* ? */ \
|
||||
| ( (((u64_t) base) & 0x00FFFFFFull) << 16) /* base 23:00 */ \
|
||||
| ( (((u64_t) limit) & 0x0000FFFFull) ) ) /* limit 15:00 */
|
||||
|
||||
typedef u64_t descriptor_t;
|
||||
|
||||
void mm_record_mmap_entry(mb_mmap_t * mmap);
|
||||
void mm_bootstrap();
|
||||
|
||||
int mm_early_map(u32_t virtual_address, u32_t physical_address,
|
||||
u32_t user_mode, u32_t writable);
|
||||
int mm_map(u32_t virtual_address, u32_t physical_address,
|
||||
u32_t user_mode, u32_t writable);
|
||||
|
||||
u32_t mm_early_page_alloc();
|
||||
u32_t mm_page_alloc();
|
||||
|
||||
void mm_print_memory_map();
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef MM_H
|
||||
#define MM_H MM_H
|
||||
|
||||
#include "hos_types.h"
|
||||
#include "hos_defines.h"
|
||||
#include "multiboot.h"
|
||||
|
||||
#define KERNEL_CODE_SEGMENT 0x08
|
||||
#define KERNEL_DATA_SEGMENT 0x10
|
||||
|
||||
typedef u32_t pagedirectory_entry_t;
|
||||
|
||||
#define NUM_PAGETABLE_ENTRIES (PAGE_SIZE / sizeof(pagedirectory_entry_t))
|
||||
|
||||
typedef pagedirectory_entry_t pagedirectory_t[NUM_PAGETABLE_ENTRIES];
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u64_t base;
|
||||
u64_t length;
|
||||
} mm_mem_range_t;
|
||||
|
||||
typedef struct mm_page_alloc_page_s
|
||||
{
|
||||
u32_t pages[PAGE_SIZE / sizeof(u32_t) - 1];
|
||||
mm_page_alloc_page_s * next;
|
||||
} mm_page_alloc_page_t;
|
||||
|
||||
/* http://courses.ece.illinois.edu/ece391/references/descriptors.pdf */
|
||||
/* granularity: 0: limit in bytes; 1: limit in pages */
|
||||
/* dpl: 0: system mode; 3: user mode */
|
||||
/* normal: 0: TSS/LDT/call gate; 1: code/data segment */
|
||||
/* code_seg: 0: data segment; 1: code segment */
|
||||
#define MAKE_DESCRIPTOR(base, limit, granularity, dpl, normal, code_seg) \
|
||||
(u64_t) ( ( (((u64_t) base) & 0xFF000000ull) << 32 ) /* base 31:24 */ \
|
||||
| ( (((u64_t) granularity) & 0x1ull) << 55 ) /* granularity */ \
|
||||
| ( ( (u64_t) 0x1ull) << 54 ) /* 32-bit */ \
|
||||
| ( (((u64_t) limit) & 0xF0000ull) << 32 ) /* limit 19:16 */ \
|
||||
| ( ( (u64_t) 0x1ull) << 47 ) /* present */ \
|
||||
| ( (((u64_t) dpl) & 0x3ull) << 45 ) /* dpl */ \
|
||||
| ( (((u64_t) normal) & 0x1ull) << 44 ) /* normal */ \
|
||||
| ( (((u64_t) code_seg) & 0x1ull) << 43 ) /* code seg */ \
|
||||
| ( ( (u64_t) 0x2ull) << 40 ) /* ? */ \
|
||||
| ( (((u64_t) base) & 0x00FFFFFFull) << 16) /* base 23:00 */ \
|
||||
| ( (((u64_t) limit) & 0x0000FFFFull) ) ) /* limit 15:00 */
|
||||
|
||||
typedef u64_t descriptor_t;
|
||||
|
||||
void mm_record_mmap_entry(mb_mmap_t * mmap);
|
||||
void mm_bootstrap();
|
||||
|
||||
int mm_early_map(u32_t virtual_address, u32_t physical_address,
|
||||
u32_t user_mode, u32_t writable);
|
||||
int mm_map(u32_t virtual_address, u32_t physical_address,
|
||||
u32_t user_mode, u32_t writable);
|
||||
|
||||
u32_t mm_early_page_alloc();
|
||||
u32_t mm_page_alloc();
|
||||
|
||||
void mm_print_memory_map();
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -1,19 +1,19 @@
|
||||
|
||||
#include "stack.h"
|
||||
#include "mm.h"
|
||||
#include "hos_defines.h"
|
||||
|
||||
void stack_bootstrap()
|
||||
{
|
||||
/*
|
||||
* running from our temporary stack while segmentation is enabled,
|
||||
* set up the "permanent" stack for use while paging
|
||||
*/
|
||||
u32_t stack_page_virt = KERNEL_STACK_TOP - PAGE_SIZE;
|
||||
for (int i = 0; i < STACK_INITIAL_SIZE; i++)
|
||||
{
|
||||
u32_t stack_page_phys = mm_page_alloc();
|
||||
mm_early_map(stack_page_virt, stack_page_phys, 0, 1);
|
||||
stack_page_virt -= PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
#include "stack.h"
|
||||
#include "mm.h"
|
||||
#include "hos_defines.h"
|
||||
|
||||
void stack_bootstrap()
|
||||
{
|
||||
/*
|
||||
* running from our temporary stack while segmentation is enabled,
|
||||
* set up the "permanent" stack for use while paging
|
||||
*/
|
||||
u32_t stack_page_virt = KERNEL_STACK_TOP - PAGE_SIZE;
|
||||
for (int i = 0; i < STACK_INITIAL_SIZE; i++)
|
||||
{
|
||||
u32_t stack_page_phys = mm_page_alloc();
|
||||
mm_early_map(stack_page_virt, stack_page_phys, 0, 1);
|
||||
stack_page_virt -= PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
|
||||
#ifndef STACK_H
|
||||
#define STACK_H
|
||||
|
||||
#define STACK_INITIAL_SIZE 2 /* number of initial stack pages */
|
||||
|
||||
void stack_bootstrap();
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef STACK_H
|
||||
#define STACK_H
|
||||
|
||||
#define STACK_INITIAL_SIZE 2 /* number of initial stack pages */
|
||||
|
||||
void stack_bootstrap();
|
||||
|
||||
#endif
|
||||
|
@ -1,54 +1,54 @@
|
||||
|
||||
ASMOBJS := $(patsubst %.asm,%.o,$(wildcard *.asm))
|
||||
COBJS := $(patsubst %.c,%.o,$(wildcard *.c))
|
||||
CXXOBJS := $(patsubst %.cc,%.o,$(wildcard *.cc))
|
||||
CDEPS := $(COBJS:.o=.dep)
|
||||
CXXDEPS := $(CXXOBJS:.o=.dep)
|
||||
DEPS := $(CDEPS) $(CXXDEPS)
|
||||
OUTPUT_FILE := $(SUBDIR)_all.o
|
||||
|
||||
ifdef SUBDIRS
|
||||
SUBDIRS_clean := $(SUBDIRS:%=%.clean)
|
||||
endif
|
||||
|
||||
all: $(OUTPUT_FILE)
|
||||
|
||||
$(OUTPUT_FILE): $(ASMOBJS) $(COBJS) $(CXXOBJS) $(SUBDIRS)
|
||||
$(LD) -r -o $@ $(ASMOBJS) $(COBJS) $(CXXOBJS) $(foreach subdir,$(SUBDIRS),$(subdir)/$(subdir)_all.o)
|
||||
|
||||
%.o: %.asm
|
||||
$(NASM) -f elf -o $@ -l $<.lst $<
|
||||
|
||||
%.o: %.c
|
||||
$(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $<
|
||||
|
||||
%.o: %.cc
|
||||
$(CXX) -c -o $@ $(CPPFLAGS) $(CXXFLAGS) $<
|
||||
|
||||
ifdef SUBDIRS
|
||||
.PHONY: $(SUBDIRS)
|
||||
$(SUBDIRS):
|
||||
$(MAKE) -C $@ SUBDIR=$@
|
||||
endif
|
||||
|
||||
# Make dependency files
|
||||
%.dep: %.c
|
||||
@set -e; rm -f $@; \
|
||||
$(CC) -MM $(CPPFLAGS) $< | sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' > $@
|
||||
|
||||
%.dep: %.cc
|
||||
@set -e; rm -f $@; \
|
||||
$(CXX) -MM $(CPPFLAGS) $< | sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' > $@
|
||||
|
||||
clean: $(SUBDIRS_clean)
|
||||
-rm -f *.o *.dep *.lst *~
|
||||
|
||||
ifdef SUBDIRS
|
||||
%.clean:
|
||||
$(MAKE) -C $* clean clean=1
|
||||
endif
|
||||
|
||||
# Include dependency files
|
||||
ifndef clean
|
||||
-include $(DEPS)
|
||||
endif
|
||||
|
||||
ASMOBJS := $(patsubst %.asm,%.o,$(wildcard *.asm))
|
||||
COBJS := $(patsubst %.c,%.o,$(wildcard *.c))
|
||||
CXXOBJS := $(patsubst %.cc,%.o,$(wildcard *.cc))
|
||||
CDEPS := $(COBJS:.o=.dep)
|
||||
CXXDEPS := $(CXXOBJS:.o=.dep)
|
||||
DEPS := $(CDEPS) $(CXXDEPS)
|
||||
OUTPUT_FILE := $(SUBDIR)_all.o
|
||||
|
||||
ifdef SUBDIRS
|
||||
SUBDIRS_clean := $(SUBDIRS:%=%.clean)
|
||||
endif
|
||||
|
||||
all: $(OUTPUT_FILE)
|
||||
|
||||
$(OUTPUT_FILE): $(ASMOBJS) $(COBJS) $(CXXOBJS) $(SUBDIRS)
|
||||
$(LD) -r -o $@ $(ASMOBJS) $(COBJS) $(CXXOBJS) $(foreach subdir,$(SUBDIRS),$(subdir)/$(subdir)_all.o)
|
||||
|
||||
%.o: %.asm
|
||||
$(NASM) -f elf -o $@ -l $<.lst $<
|
||||
|
||||
%.o: %.c
|
||||
$(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $<
|
||||
|
||||
%.o: %.cc
|
||||
$(CXX) -c -o $@ $(CPPFLAGS) $(CXXFLAGS) $<
|
||||
|
||||
ifdef SUBDIRS
|
||||
.PHONY: $(SUBDIRS)
|
||||
$(SUBDIRS):
|
||||
$(MAKE) -C $@ SUBDIR=$@
|
||||
endif
|
||||
|
||||
# Make dependency files
|
||||
%.dep: %.c
|
||||
@set -e; rm -f $@; \
|
||||
$(CC) -MM $(CPPFLAGS) $< | sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' > $@
|
||||
|
||||
%.dep: %.cc
|
||||
@set -e; rm -f $@; \
|
||||
$(CXX) -MM $(CPPFLAGS) $< | sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' > $@
|
||||
|
||||
clean: $(SUBDIRS_clean)
|
||||
-rm -f *.o *.dep *.lst *~
|
||||
|
||||
ifdef SUBDIRS
|
||||
%.clean:
|
||||
$(MAKE) -C $* clean clean=1
|
||||
endif
|
||||
|
||||
# Include dependency files
|
||||
ifndef clean
|
||||
-include $(DEPS)
|
||||
endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user