${KERNELBIN}: ${OBJS}
${LD} -z noexecstack -m elf_i386 -M -T$(LINKSCRIPT) $(OBJS) -o $@ > $(SYSTEMMAP)
nm -a $@ > kernel.sym
- rm kernel/setup.c.o
+ #rm kernel/setup.c.o
%.S.o: %.S ${HEADER_FILES}
${CC} ${CFLAGS} $< -o $@
void parse_cmdline(const char *cmdline);
void init_vbe(void *, void *);
+
+// ticks < 0 代表永远等待
+void boot_delay(int ticks) {
+ char chs[] = {'\\', '-', '/', '-'};
+ uint32_t cnt = 0;
+
+ printk(" ");
+ asm("sti;");
+ while (true) {
+ if (ticks == 0) {
+ break;
+ }
+
+ if (ticks > 0) {
+ ticks--;
+ }
+
+ printk("\b%c", chs[(cnt++ / 3) % sizeof(chs)]);
+ asm("hlt");
+ }
+ asm("cli;");
+ printk("\b \b");
+}
+
+void init_ttys();
+void setup_gdt();
+void setup_idt();
+void setup_gates();
+void set_tss();
+void setup_i8253(uint16_t);
+void setup_boot_irqs();
+
void check_kernel(unsigned long addr, unsigned long magic) {
+ init_ttys();
+
+ printk("setup gdt\n");
+ setup_gdt();
+
+ printk("setup idt\n");
+ setup_idt();
+
+ printk("setup trap and interrupt gates\n");
+ setup_gates();
+
+ // 在初始化阶段一直运行在特权级0上
+ // 在正在进入用户态前,所有中断都不会涉及特权级变化
+ // 自然就不会有栈切换
+ // 因此这里set_tss里的tss.esp0是不用初始化的
+ set_tss();
+
+ setup_boot_irqs();
+
+ setup_i8253(100);
+
+ boot_delay(DEFAULT_BOOT_DELAY_TICKS);
+
if (magic != MULTIBOOT2_BOOTLOADER_MAGIC) {
printk("Your boot loader does not support multiboot.\n");
- while (1) {
- }
+ boot_delay(-1);
}
-
unsigned long total_size = *((unsigned long *)addr);
struct multiboot_tag *tag = (struct multiboot_tag *)(addr + 8); // 跳过中间的 reserved 字段
printk("total size: %d tags: %x\n", total_size, tag);
-
+ boot_delay(DEFAULT_BOOT_DELAY_TICKS);
struct multiboot_tag_basic_meminfo *mminfo = 0;
struct multiboot_tag_bootdev *bootdev = 0;
struct multiboot_tag_mmap *mmap_tag = 0;
unsigned long size = (tag->size + 7) & (~7UL);
tag = (struct multiboot_tag *)(((unsigned long)tag) + size);
}
+
+ boot_delay(DEFAULT_BOOT_DELAY_TICKS);
#if 0
multiboot_info_t *mbi = (multiboot_info_t *)addr;
}
init_boot_params(mbi);
+
+ boot_delay(DEFAULT_BOOT_DELAY_TICKS);
#endif
}
extern void *kernel_begin;
extern void *kernel_end;
extern void *bootmem_bitmap_begin;
-extern void init_default_tty_before_paging();
+
void init_system_info() {
system.kernel_begin = &kernel_begin;
system.kernel_end = &kernel_end;
printk("boot device: bios dev %x partition %x sub partition %x\n", boot_params.biosdev, boot_params.partition,
boot_params.sub_partition);
printk("mem lower %uKB upper %uKB\n", boot_params.mem_lower >> 10, boot_params.mem_upper >> 10);
+
+ boot_delay(DEFAULT_BOOT_DELAY_TICKS);
}
.global kernel_entry
.global main
.extern check_kernel
-.extern init_default_tty_before_paging
.extern init_system_info
.extern setup_kernel
.extern init_pgd
addl $8, %esp
movl $root_task + TASK_SIZE, %esp
- call init_default_tty_before_paging
call init_system_info
call setup_kernel
ide_pci_controller.pci = pci;
- printk("channel0: cmd %04x ctl %04x channel1: cmd %04x ctl %04x\n", ATA_CHL0_CMD_BASE, ATA_CHL0_CTL_BASE,
+ printd("channel0: cmd %04x ctl %04x channel1: cmd %04x ctl %04x\n", ATA_CHL0_CMD_BASE, ATA_CHL0_CTL_BASE,
ATA_CHL1_CMD_BASE, ATA_CHL1_CTL_BASE);
// printl(18, "channel0: cmd %04x ctl %04x channel1: cmd %04x ctl %04x", HD_CHL0_CMD_BASE, HD_CHL0_CTL_BASE,
// HD_CHL1_CMD_BASE, HD_CHL1_CTL_BASE);
// reboot();
}
- printd("[%02x]", scan_code);
+ // printd("[%02x]", scan_code);
if (scan_code == 0x3B) { // F1
tty_switch(&default_tty);
extern void init_i8259();
extern void mask_i8259();
+int enable_i8259_irq(unsigned int irq);
+int disable_i8259_irq(unsigned int irq);
+void mask_ack_i8259_irq(unsigned int irq);
+void ack_i8259_irq(unsigned int irq);
+
#if 0
=Programmable Interrupt Controller=
__asm__ __volatile__("pushl %0; popfl" ::"g"(x) : "memory", "cc"); \
} while (0)
+#define IRQ_CLOCK 0x00
+#define IRQ_KEYBOARD 0x01
+#define IRQ_CASCADE 0x02
+#define IRQ_DISK 0x0E
+
#endif //_IRQ_H
MPO_KEYBOARD = 50,
MPO_IDE = 1,
};
+
+int sprintf(char *str, const char *fmtstr, ...);
extern char etext, edata, end;
-extern char gdtr[6], idtr[6];
-#define lgdt() __asm__ __volatile__("lgdt gdtr")
-#define sgdt() __asm__ __volatile__("sgdt gdtr")
-#define lidt() __asm__ __volatile__("lidt idtr")
-#define sidt() __asm__ __volatile__("sidt idtr")
-
-#define cli() __asm__ __volatile__("cli")
-#define sti() __asm__ __volatile__("sti")
+#define cli() asm volatile("cli")
+#define sti() asm volatile("sti")
#define nop() asm volatile("nop")
#define mb() asm volatile("" ::: "memory")
#define disableIRQ() cli()
void user_task_entry();
extern volatile int reenter;
+
+#define DEFAULT_BOOT_DELAY_TICKS 30
+void boot_delay(int ticks);
#endif
#endif //_SYSTEM_H
/*
*--------------------------------------------------------------------------
* File Name: entry.S
- *
+ *
* Description: none
- *
- *
+ *
+ *
* Author: Zhao Yanbai [zhaoyanbai@126.com]
- *
+ *
* Version: 1.0
* Create Date: Thu Jul 09 19:56:40 2009
* Last Update: Thu Jul 09 19:56:40 2009
- *
+ *
*--------------------------------------------------------------------------
*/
#define ASM
ERRORCODE (GeneralProtection)
ERRORCODE (PageFault)
NOERRCODE (CoprocError)
-
task_union *tsk;
tsk = alloc_task_union();
- printk("fork task %08x flags %08x\n", tsk, flags);
+ printd("fork task %08x flags %08x\n", tsk, flags);
if (tsk == NULL) {
panic("can not malloc PCB");
}
pt_regs_t *child_regs = ((pt_regs_t *)(TASK_SIZE + (unsigned long)tsk)) - 1;
- printk("child regs: %x %x\n", child_regs, regs);
+ printd("child regs: %x %x\n", child_regs, regs);
memcpy(child_regs, regs, sizeof(*regs));
tsk->esp0 = TASK_SIZE + (unsigned long)tsk;
child_regs->eax = 0;
child_regs->eflags |= 0x200; // enable IF
- printk("tsk %08x child_regs esp %08x esp0 %08x\n", tsk, tsk->esp, tsk->esp0);
+ printd("task %08x child_regs esp %08x esp0 %08x\n", tsk, tsk->esp, tsk->esp0);
tsk->state = TASK_INITING;
return (int)tsk->pid;
}
-int sysc_fork(pt_regs_t regs) { return do_fork(®s, 0); }
\ No newline at end of file
+int sysc_fork(pt_regs_t regs) { return do_fork(®s, 0); }
};
void do_i8259_IRQ(pt_regs_t *regs, unsigned int irq) {}
+
+__attribute__((regparm(1))) void boot_irq_handler(pt_regs_t *regs) {
+ unsigned int irq = regs->irq;
+ if (irq != 0 && irq != 1) {
+ panic("invalid irq %d\n", irq);
+ }
+
+ assert(irq_disabled());
+
+ // 屏蔽当前中断
+ disable_i8259_irq(irq);
+
+ // 发送EOI
+ ack_i8259_irq(irq);
+
+ // 解除屏蔽当前中断
+ enable_i8259_irq(irq);
+}
/*
*--------------------------------------------------------------------------
* File Name: interrupts.S
- *
+ *
* Description: none
- *
- *
+ *
+ *
* Author: Zhao Yanbai [zhaoyanbai@126.com]
- *
+ *
* Version: 1.0
* Create Date: Thu Jul 16 18:54:08 2009
* Last Update: Wed Feb 10 23:10:56 2010
- *
+ *
*--------------------------------------------------------------------------
*/
#define ASM
.global no_irq_handler
no_irq_handler:
pushl $0xFFFFFFFF
-jmp _irq_handler
+jmp _boot_irq_handler
DEF_IRQ(0,0)
movl %esp, %eax
call irq_handler
-
+
RESTORE_REGS
addl $4, %esp
- iret
\ No newline at end of file
+ iret
+
+
+
+.extern boot_irq_handler
+_boot_irq_handler:
+ SAVE_REGS
+
+ // ebp指向栈桢
+ movl $-TASK_SIZE, %ebp
+ andl %esp, %ebp
+
+ movw %ss, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+
+ movl %esp, %eax
+ call boot_irq_handler
+
+ RESTORE_REGS
+ addl $4, %esp
+ iret
+
+
+.global _boot_clk_irq_handler
+.global _boot_kbd_irq_handler
+
+_boot_clk_irq_handler:
+ push $0x00;
+ jmp _boot_irq_handler
+_boot_kbd_irq_handler:
+ push $0x01;
+ jmp _boot_irq_handler
init_mm();
// printk("kernel: %08x - %08x\n", system.kernel_begin, system.kernel_end);
-
- setup_gdt();
- setup_idt();
- setup_gate();
- set_tss();
-
- setup_i8253(100);
+ boot_delay(DEFAULT_BOOT_DELAY_TICKS);
setup_sysc();
+ boot_delay(DEFAULT_BOOT_DELAY_TICKS);
cnsl_init();
+ boot_delay(DEFAULT_BOOT_DELAY_TICKS);
printl(MPL_TITLE, " KERNEL MONITOR");
setup_tasks();
-
- setup_irqs();
+ boot_delay(DEFAULT_BOOT_DELAY_TICKS);
setup_pci();
+ boot_delay(DEFAULT_BOOT_DELAY_TICKS);
detect_cpu();
+ boot_delay(DEFAULT_BOOT_DELAY_TICKS);
printk(version);
+ boot_delay(DEFAULT_BOOT_DELAY_TICKS);
extern tty_t monitor_tty;
- tty_switch(&monitor_tty);
+ // tty_switch(&monitor_tty);
+
+ boot_delay(DEFAULT_BOOT_DELAY_TICKS);
+
+ setup_i8253(100);
+ setup_irqs();
void ide_init();
ide_init();
#include <syscall.h>
#include <system.h>
+System system;
+TSS_t tss;
+Desc idt[NIDT] __attribute__((__aligned__(8)));
+Desc gdt[NGDT] __attribute__((__aligned__(8)));
+char gdtr[6] __attribute__((__aligned__(4)));
+char idtr[6] __attribute__((__aligned__(4)));
+
+extern char _gdtr[6];
+extern char _idtr[6];
+
+volatile int reenter = -1;
+
+#if 0
+void setup_gdt_before_pageing() {
+ pDesc pdesc;
+ // change to new gdt.
+ asm volatile("sgdt _gdtr");
+ Desc *_gdt = (Desc *)va2pa(gdt);
+ memcpy((void *)_gdt, (void *)(_gdtr + 2), *((uint16_t *)(_gdtr + 0)));
+
+ //
+ *((uint16_t *)(_gdtr + 0)) = NGDT * sizeof(Desc);
+ *((uint32_t *)(_gdtr + 2)) = (uint32_t)_gdt;
+ asm volatile("sgdt _gdtr");
+ memcpy(_gdt + INDEX_UCODE, _gdt + INDEX_KCODE, sizeof(Desc));
+ memcpy(_gdt + INDEX_UDATA, _gdt + INDEX_KDATA, sizeof(Desc));
+ pdesc = _gdt + INDEX_UCODE;
+ pdesc->seg.DPL = 3;
+ pdesc = _gdt + INDEX_UDATA;
+ pdesc->seg.DPL = 3;
+}
+#endif
+
void setup_gdt() {
pDesc pdesc;
// change to new gdt.
- sgdt();
- memcpy(gdt, (void *)pa2va(*((unsigned long *)(gdtr + 2))), *((unsigned short *)gdtr));
+ asm volatile("sgdt gdtr");
+
+ // 复制旧的GDT
+ memcpy(gdt, (void *)pa2va(*((uint32_t *)(gdtr + 2))), *((uint16_t *)(gdtr + 0)));
*((unsigned short *)gdtr) = NGDT * sizeof(Desc);
*((unsigned long *)(gdtr + 2)) = (unsigned long)gdt;
- lgdt();
+
+ asm volatile("lgdt gdtr");
+
memcpy(gdt + INDEX_UCODE, gdt + INDEX_KCODE, sizeof(Desc));
memcpy(gdt + INDEX_UDATA, gdt + INDEX_KDATA, sizeof(Desc));
pdesc = gdt + INDEX_UCODE;
pdesc->seg.DPL = 3;
}
+// 中断门和陷阱门的区别是
+// 通过中断门进入中断服务程序CPU会自动将中断关闭,也就是将EFLAGS的IF位清0
+// 通过陷阱门进入服务程序时则维持IF标志位不变
void setup_idt() {
*((unsigned short *)idtr) = NIDT * sizeof(Gate);
*((unsigned long *)(idtr + 2)) = (unsigned long)idt;
- lidt();
+ asm volatile("lidt idtr");
}
-void setup_gate() {
- int i;
+void setup_gates() {
set_sys_int(0x00, TRAP_GATE, PRIVILEGE_KRNL, DivideError);
set_sys_int(0x01, TRAP_GATE, PRIVILEGE_KRNL, Debug);
set_sys_int(0x02, INTR_GATE, PRIVILEGE_KRNL, NMI);
set_sys_int(0x0E, TRAP_GATE, PRIVILEGE_KRNL, PageFault);
set_sys_int(0x10, TRAP_GATE, PRIVILEGE_KRNL, CoprocError);
- for (i = 0x11; i < 0x20; i++) set_sys_int(i, INTR_GATE, PRIVILEGE_KRNL, no_irq_handler);
+ for (int i = 0x11; i < 0x20; i++) {
+ set_sys_int(i, INTR_GATE, PRIVILEGE_KRNL, no_irq_handler);
+ }
+
+ for (int i = 0x20; i < 256; i++) {
+ set_sys_int(i, INTR_GATE, PRIVILEGE_KRNL, no_irq_handler);
+ }
+}
+
+void ide_irq();
+
+void default_irq_handler(unsigned int irq, pt_regs_t *regs, void *dev_id) { printk("default irq handler %d \n", irq); }
- for (i = 0x20; i < 256; i++) set_sys_int(i, INTR_GATE, PRIVILEGE_KRNL, no_irq_handler);
+void init_i8259();
+void setup_irqs() {
set_sys_int(0x20, INTR_GATE, PRIVILEGE_KRNL, irq_0x00_handler);
set_sys_int(0x21, INTR_GATE, PRIVILEGE_KRNL, irq_0x01_handler);
set_sys_int(0x22, INTR_GATE, PRIVILEGE_KRNL, irq_0x02_handler);
set_sys_int(0x2D, INTR_GATE, PRIVILEGE_KRNL, irq_0x0D_handler);
set_sys_int(0x2E, INTR_GATE, PRIVILEGE_KRNL, irq_0x0E_handler);
set_sys_int(0x2F, INTR_GATE, PRIVILEGE_KRNL, irq_0x0F_handler);
-}
-
-void ide_irq();
-
-void default_irq_handler(unsigned int irq, pt_regs_t *regs, void *dev_id) { printk("default irq handler %d \n", irq); }
-
-void setup_irqs() {
- extern void init_i8259();
- init_i8259();
for (int i = 0; i < NR_IRQS; i++) {
irq_desc[i] = no_irq_desc;
// 清除8259A的级连中断引脚的中断屏蔽位
// 以让从片的中断在放开后能发送到CPU
- open_irq(2);
+ open_irq(IRQ_CASCADE);
// 打开支持的中断
- open_irq(0x00);
- open_irq(0x01);
- open_irq(0x0E);
+ open_irq(IRQ_CLOCK);
+ open_irq(IRQ_KEYBOARD);
+ open_irq(IRQ_DISK);
+}
+
+void boot_irq_handler();
+void setup_boot_irqs() {
+ init_i8259();
+
+ // clock
+ set_sys_int(0x20 + IRQ_CLOCK, INTR_GATE, PRIVILEGE_KRNL, _boot_clk_irq_handler);
+
+ // keyboard
+ set_sys_int(0x20 + IRQ_KEYBOARD, INTR_GATE, PRIVILEGE_KRNL, _boot_kbd_irq_handler);
+
+ // 打开支持的中断
+ enable_i8259_irq(IRQ_CLOCK);
+ enable_i8259_irq(IRQ_KEYBOARD);
}
void set_tss_gate(u32 vec, u32 addr, u32 limit) {
return 0;
}
-
-System system;
-TSS_t tss;
-Desc idt[NIDT] __attribute__((__aligned__(8)));
-Desc gdt[NGDT] __attribute__((__aligned__(8)));
-char gdtr[6] __attribute__((__aligned__(4)));
-char idtr[6] __attribute__((__aligned__(4)));
-
-volatile int reenter = -1;
\ No newline at end of file
int pid = do_fork(®s, FORK_KRNL);
- printk("kernel[%s] task pid is %d\n", name, pid);
+ printd("kernel[%s] task pid is %d\n", name, pid);
}
// 测试用的代码
while (1) {
asm("hlt;");
}
-}
\ No newline at end of file
+}
unsigned long *p = (unsigned long *)(pa2va(current->cr3));
- printk("page dir : %x %x %x %x\n", p, pt_text_page, ring3_text_page);
- printk("pt bss page %x %x", pt_bss_page, ring3_bss_page);
+ printd("page dir : %x %x %x %x\n", p, pt_text_page, ring3_text_page);
+ printd("pt bss page %x %x", pt_bss_page, ring3_bss_page);
// text: 0x0800_0000
// bss: 0x3000_0000
// eip --> edx
// esp --> ecx
asm volatile("sysexit;" ::"d"(0x08000000), "c"(0x30000000 + PAGE_SIZE - 100));
-}
\ No newline at end of file
+}
// 所以大致可以分出8个tty
// 每个的起始地址以0x1000对齐
const uint32_t PHY_VADDR = 0xB8000;
-#define VADDR ((uint32_t)pa2va(PHY_VADDR))
+const uint32_t VADDR = (uint32_t)pa2va(PHY_VADDR);
#define TTY_VRAM_SIZE (0x1000)
#define MAX_X 80
}
}
-void init_default_tty_before_paging() {
- default_tty.fg_color = TTY_FG_HIGHLIGHT | TTY_GREEN; // 高亮
- default_tty.bg_color = TTY_BLACK; // 不闪
- default_tty.base_addr = PHY_VADDR;
- default_tty.xpos = 0;
- default_tty.ypos = 0;
-}
-
void init_tty(tty_t *tty, const char *name, unsigned long base) {
assert(0 != tty);
tty->bg_color = TTY_BLACK; // 不闪
tty->base_addr = base;
+
+ for (int i = 0; i < TTY_VRAM_SIZE; i += 2) {
+ uint8_t *p = (uint8_t *)base;
+ p[i + 0] = ' ';
+ p[i + 1] = (tty->bg_color << 4) | tty->fg_color;
+ }
}
void init_ttys() {
tty_clear(&monitor_tty);
tty_clear(&debug_tty);
- // 恢复在分页前的输出位置
- default_tty.xpos = xpos;
- default_tty.ypos = ypos;
-
current_tty = &default_tty;
}
int sysdebug(unsigned int v) { return syscall1(SYSC_DEBUG, v); }
int pause(unsigned long tick) { return syscall1(SYSC_PAUSE, tick); }
+
+int vsprintf(char *buf, const char *fmt, char *args);
+int sprintf(char *str, const char *fmtstr, ...) {
+ char *args = (char *)(((char *)&fmtstr) + 4);
+
+ vsprintf(str, fmtstr, args);
+
+ return 0;
+}
#include <string.h>
#include <system.h>
-static void e820_print_type(unsigned long type) {
+static void get_e820_size(uint32_t size, char *buf) {
+ const char *fmt = "%3u %s";
+ if (size < (1 << 10)) {
+ sprintf(buf, fmt, size, "B");
+ } else if (size < (1 << 20)) {
+ sprintf(buf, fmt, size >> 10, "KB");
+ } else if (size < (1 << 30)) {
+ sprintf(buf, fmt, size >> 20, "MB");
+ } else {
+ sprintf(buf, fmt, size >> 30, "GB");
+ }
+}
+
+// static void e820_print_type(unsigned long type) {
+// switch (type) {
+// case E820_RAM:
+// printk("RAM");
+// break;
+// case E820_RESERVED:
+// printk("RESERVED");
+// break;
+// case E820_ACPI:
+// printk("ACPI");
+// break;
+// case E820_NVS:
+// printk("NVS");
+// break;
+// case E820_UNUSABLE:
+// printk("UNUSABLE");
+// break;
+// default:
+// printk("type %x", type);
+// break;
+// }
+// }
+
+static void get_e820_type(uint32_t type, char *buf) {
switch (type) {
case E820_RAM:
- printk("RAM");
+ sprintf(buf, "%s", "RAM");
break;
case E820_RESERVED:
- printk("RESERVED");
+ sprintf(buf, "%s", "RESERVED");
break;
case E820_ACPI:
- printk("ACPI");
+ sprintf(buf, "%s", "ACPI");
break;
case E820_NVS:
- printk("NVS");
+ sprintf(buf, "%s", "NVS");
break;
case E820_UNUSABLE:
- printk("UNUSABLE");
+ sprintf(buf, "%s", "UNUSABLE");
break;
default:
- printk("type %x", type);
+ sprintf(buf, "type %x", type);
break;
}
}
void e820_print_map() {
unsigned int i = 0;
-
for (i = 0; i < boot_params.e820map.map_cnt; ++i) {
struct e820_entry *p = boot_params.e820map.map + i;
- printk(" [%02d] 0x%010lX - 0x%010lX size %- 10u %8dKB %5dMB ", i, p->addr, (p->addr + p->size - 1),
- (uint32_t)p->size, (uint32_t)(p->size >> 10), (uint32_t)(p->size >> 20));
-
- e820_print_type(p->type);
-
- printk("\n");
+ // printk(" [%02d] 0x%010lX - 0x%010lX size %- 10u %8dKB %5dMB ", i, p->addr, (p->addr + p->size - 1),
+ // (uint32_t)p->size, (uint32_t)(p->size >> 10), (uint32_t)(p->size >> 20));
+ char size_buf[16];
+ char type_buf[16];
+ get_e820_size((uint32_t)p->size, size_buf);
+ get_e820_type(p->type, type_buf);
+ printk(" [%02d] 0x%08lX - 0x%08lX %7s %s\n", i, p->addr, (p->addr + p->size - 1), size_buf, type_buf);
}
}
printk("init bootmem alloc...\n");
extern void init_bootmem();
init_bootmem();
+ boot_delay(DEFAULT_BOOT_DELAY_TICKS);
printk("init global paging...\n");
init_paging();
-
- // 只能将这个调用放在此处
- // 在这之前是没开启页映射用的是物理地址
- // 在这之后需要用到线性地址来定位显存
- init_ttys();
+ boot_delay(DEFAULT_BOOT_DELAY_TICKS);
printk("init buddy system...\n");
extern void init_buddy_system();
init_buddy_system();
+ boot_delay(DEFAULT_BOOT_DELAY_TICKS);
printk("init kmem caches...\n");
extern void init_kmem_caches();
init_kmem_caches();
printk("memory init finished...\n");
+ boot_delay(DEFAULT_BOOT_DELAY_TICKS);
}