diff --git a/boot/interrupt.asm b/boot/interrupt.asm index cd1febc..8b78bc5 100644 --- a/boot/interrupt.asm +++ b/boot/interrupt.asm @@ -52,7 +52,7 @@ ISR_NOERRCODE 31 ; 通用中断处理程序 isr_common_stub: - pusha ; 存储所有寄存器 + pusha mov ax, ds push eax ; 存储ds @@ -62,17 +62,17 @@ isr_common_stub: mov es, ax mov fs, ax mov gs, ax - call isr_handler ; 调用C语言处理函数 - pop eax ; 恢复各段 + call isr_handler ; call isr_headler(registers_t reg); + pop eax ; 恢复 mov ds, ax mov es, ax mov fs, ax mov gs, ax - popa ; 弹出所有寄存器 + popa add esp, 8 ; 弹出错误码和中断ID - iret ; 从中断返回 + iret %macro IRQ 2 global irq%1 diff --git a/boot/io.asm b/boot/io.asm index e90844a..76aa6b2 100644 --- a/boot/io.asm +++ b/boot/io.asm @@ -9,6 +9,7 @@ global tss_flush, gdt_flush, switch_to section .text + switch_to: mov eax, [esp+4] diff --git a/driver/acpi.c b/driver/acpi.c new file mode 100644 index 0000000..673d8a9 --- /dev/null +++ b/driver/acpi.c @@ -0,0 +1,278 @@ +#include "../include/acpi.h" +#include "../include/memory.h" +#include "../include/graphics.h" +#include "../include/io.h" +#include "../include/isr.h" +#include "../include/timer.h" + +uint16_t SLP_TYPa; +uint16_t SLP_TYPb; +uint32_t SMI_CMD; +uint8_t ACPI_ENABLE; +uint8_t ACPI_DISABLE; +uint32_t *PM1a_CNT; +uint32_t *PM1b_CNT; +uint8_t PM1_CNT_LEN; +uint16_t SLP_EN; +uint16_t SCI_EN; + +acpi_rsdt_t *rsdt; // root system descript table +acpi_facp_t *facp; // fixed ACPI table + +int acpi_enable() { + int i; + + // check if enable ACPI + if (io_in16((uint32_t) PM1a_CNT) & SCI_EN) { + printf("ACPI already enable!\n"); + return 0; + } + + if (SMI_CMD && ACPI_ENABLE) { + // send ACPI_ENABLE cmd + io_out8((uint16_t) + SMI_CMD, ACPI_ENABLE); + + // wait enable + for (i = 0; i < 300; i++) { + if (io_in16((uint32_t) PM1a_CNT) & SCI_EN) { + break; + } + clock_sleep(5); + } + // wait enable + if (PM1b_CNT) { + for (i = 0; i < 300; i++) { + if (io_in16((uint32_t) PM1b_CNT) & SCI_EN) { + break; + } + clock_sleep(5); + } + } + // check enable status + if (i < 300) { + printf("[acpi]: Enable ACPI\n"); + return 0; + } else { + printf("Counld't enable ACPI\n"); + return -1; + } + } + return -1; +} + +int acpi_disable() { + int i; + + if (!io_in16((uint16_t)PM1a_CNT) &SCI_EN) + return 0; + + if (SMI_CMD || ACPI_DISABLE) { + io_out8((uint16_t) + SMI_CMD, ACPI_DISABLE); + + for (i = 0; i < 300; i++) { + if (!io_in16((uint16_t)PM1a_CNT) &SCI_EN) + break; + clock_sleep(5); + } + + for (i = 0; i < 300; i++) { + if (!io_in16((uint16_t)PM1b_CNT) &SCI_EN) + break; + clock_sleep(5); + } + + if (i < 300) { + printf("ACPI Disable!\n"); + return 0; + } else { + printf("Could't disable ACPI\n"); + return -1; + } + } + return -1; +} + +uint8_t *AcpiGetRSDPtr() { + uint32_t *addr; + uint32_t *rsdt; + uint32_t ebda; + + for (addr = (uint32_t *) 0x000E0000; addr < (uint32_t *) 0x00100000; addr += 0x10 / sizeof(addr)) { + rsdt = AcpiCheckRSDPtr(addr); + if (rsdt) { + return rsdt; + } + } + + // search extented bios data area for the root system description pointer signature + ebda = *(uint16_t * ) + 0x40E; + ebda = ebda * 0x10 & 0xfffff; + for (addr = (uint32_t *) ebda; addr < (uint32_t * )(ebda + 1024); addr += 0x10 / sizeof(addr)) { + rsdt = AcpiCheckRSDPtr(addr); + if (rsdt) { + return rsdt; + } + } + return NULL; +} + +void power_reset() { + uint8_t val; + if (!SCI_EN) + return; + while (1) { + // write ICH port + io_out8(0x92, 0x01); + // send RESET_VAL + io_out8((uint32_t) facp->RESET_REG.address, facp->RESET_VALUE); + } +} + +void power_off() { + if (!SCI_EN) + return; + while (1) { + printf("[acpi] send power off command!\n"); + io_out16((uint32_t) PM1a_CNT, SLP_TYPa | SLP_EN); + if (!PM1b_CNT) { + io_out16((uint32_t) PM1b_CNT, SLP_TYPb | SLP_EN); + } + } +} + +int AcpiCheckHeader(void *ptr, uint8_t *sign) { + uint8_t * bptr = ptr; + uint32_t len = *(bptr + 4); + uint8_t checksum = 0; + + if (!memcmp(bptr, sign, 4)) { + while (len-- > 0) { + checksum += *bptr++; + } + return 0; + } + return -1; +} + +uint8_t *AcpiCheckRSDPtr(void *ptr) { + char *sign = "RSD PTR "; + acpi_rsdptr_t *rsdp = ptr; + uint8_t * bptr = ptr; + uint32_t i = 0; + uint8_t check = 0; + + // check signature + if (!memcmp(sign, bptr, 8)) { + printf("[acpi] rsdp found at %0x\n", bptr); + for (i = 0; i < sizeof(acpi_rsdptr_t); i++) { + check += *bptr; + bptr++; + } + if (!check) { + return (uint8_t * ) + rsdp->rsdt; + } + } + return NULL; +} + +uint32_t AcpiGetMadtBase() { + uint32_t entrys = rsdt->length - HEADER_SIZE / 4; + uint32_t **p = &(rsdt->entry); + acpi_madt_t *madt = NULL; + + while (--entrys) { + if (!AcpiCheckHeader(*p, "APIC")) { + madt = (acpi_madt_t *) *p; + return madt; + } + p++; + } + return 0; +} + +static int AcpiSysInit() { + + uint32_t **p; + uint32_t entrys; + uint32_t dsdtlen; + + rsdt = (acpi_rsdt_t *) AcpiGetRSDPtr(); + if (!rsdt || AcpiCheckHeader(rsdt, "RSDT") < 0) { + printf("No ACPI\n"); + return -1; + } + + entrys = rsdt->length - HEADER_SIZE / 4; + p = &(rsdt->entry); + while (entrys--) { + if (!AcpiCheckHeader(*p, "FACP")) { + facp = (acpi_facp_t *) *p; + + ACPI_ENABLE = facp->ACPI_ENABLE; + ACPI_DISABLE = facp->ACPI_DISABLE; + + SMI_CMD = facp->SMI_CMD; + + PM1a_CNT = facp->PM1a_CNT_BLK; + PM1b_CNT = facp->PM1b_CNT_BLK; + + PM1_CNT_LEN = facp->PM1_CNT_LEN; + + SLP_EN = 1 << 13; + SCI_EN = 1; + + uint8_t * S5Addr; + uint32_t dsdtlen; + + if (!AcpiCheckHeader(facp->DSDT, "DSDT")) { + S5Addr = &(facp->DSDT->definition_block); + dsdtlen = facp->DSDT->length - HEADER_SIZE; + while (dsdtlen--) { + if (!memcmp(S5Addr, "_S5_", 4)) { + break; + } + S5Addr++; + } + + if (dsdtlen) { + // check valid \_S5 + if (*(S5Addr - 1) == 0x08 || (*(S5Addr - 2) == 0x08 && *(S5Addr - 1) == '\\')) { + S5Addr += 5; + S5Addr += ((*S5Addr & 0xC0) >> 6) + 2; + + if (*S5Addr == 0x0A) { + S5Addr++; + } + SLP_TYPa = *(S5Addr) << 10; + S5Addr++; + if (*S5Addr == 0x0A) { + S5Addr++; + } + SLP_TYPb = *(S5Addr) << 10; + S5Addr++; + } else { + printf("[acpi] \\_S5 parse error!\n"); + } + } else { + printf("[acpi] \\_S5 not present!\n"); + } + } else { + printf("[acpi] no found DSDT table\n"); + } + return 0; + } + ++p; + } + printf("[acpi] No valid FACP present\n"); +} + +void acpi_install() { + AcpiSysInit(); + acpi_enable(); + // power init + // AcpiPowerInit(); +} \ No newline at end of file diff --git a/include/acpi.h b/include/acpi.h new file mode 100644 index 0000000..5d044fe --- /dev/null +++ b/include/acpi.h @@ -0,0 +1,218 @@ +#ifndef CRASHPOWEROS_ACPI_H +#define CRASHPOWEROS_ACPI_H + +#include +#include + +#define HEADER_SIZE 36 + +#define ACPI_TABLE_RSDT ((void *)rsdt) +#define ACPI_TABLE_FACP ((void *)facp) + +#pragma pack(push, 1) +typedef struct +{ + uint8_t addressid; + uint8_t register_bitwidth; + uint8_t register_bitoffset; + uint8_t access_size; + uint64_t address; +} acpi_address_t; +#pragma pack(pop) + +#pragma pack(push, 1) +typedef struct +{ + uint8_t signature[8]; + uint8_t checksum; + uint8_t oem_id[6]; + uint8_t revision; + uint32_t rsdt; +} acpi_rsdptr_t; +#pragma pack(pop) + +#pragma pack(push, 1) +typedef struct +{ + uint8_t signature[4]; // signature "RSDT" + uint32_t length; + uint8_t revision; + uint8_t checksum; + uint8_t oem_id[6]; + uint8_t oem_tableid[8]; + uint32_t oem_revision; + uint32_t creator_id; + uint32_t creator_revision; + uint32_t *entry; +} acpi_rsdt_t; +#pragma pack(pop) + +#pragma pack(push, 1) +typedef struct +{ + uint8_t signature[4]; + uint32_t length; + uint8_t revision; + uint8_t checksum; + uint8_t oem_id[6]; + uint8_t oem_tableid[8]; + uint32_t oem_revision; + uint32_t creator_id; + uint8_t definition_block; +} acpi_dsdt_t; +#pragma pack(pop) + +#pragma pack(push, 1) +typedef struct +{ + uint8_t signature[4]; + uint32_t length; + uint8_t FADT_major_version; + uint8_t checksum; + uint8_t ome_id[6]; + uint8_t oem_tableid[8]; + uint32_t oem_revision; + uint32_t creator_id; + uint32_t creator_revision; + + uint32_t FIRMWARE_CTRL; + acpi_dsdt_t *DSDT; + + // no longer in use + uint8_t unused0; + + uint8_t PM_profile; + uint16_t SCI_INT; + uint32_t SMI_CMD; + uint8_t ACPI_ENABLE; + uint8_t ACPI_DISABLE; + uint8_t S4BIOS_REQ; + uint8_t PSTATE_CNT; + uint32_t PM1a_EVT_BLK; + uint32_t PM1b_EVT_BLK; + uint32_t PM1a_CNT_BLK; + uint32_t PM1b_CNT_BLK; + uint32_t PM2_CNT_BLK; + uint32_t PM_TMR_BLK; + uint32_t GPE0_BLK; + uint32_t GPE1_BLK; + uint8_t PM1_EVT_LEN; + uint8_t PM1_CNT_LEN; + uint8_t PM2_CNT_LEN; + uint8_t PM_TMR_LEN; + uint8_t GPE0_BLK_LEN; + uint8_t GPE1_BLK_LEN; + uint8_t GPE1_BASE; + uint8_t CST_CNT; + uint16_t P_LVL2_LAT; + uint16_t P_LVL3_LAT; + uint16_t FLUSH_SIZE; + uint16_t FLUSH_STRIDE; + uint8_t DUTY_OFFSET; + uint8_t DUTY_WIDTH; + uint8_t DAY_ALRM; + uint8_t MON_ALRM; + uint8_t CENTURY; + + // reserved in ACPI 1.0,used in since ACPI 2.0+ + uint16_t IAPC_BOOT_ARCH; + uint8_t unused1; + uint32_t flags; + + acpi_address_t RESET_REG; + uint8_t RESET_VALUE; + uint16_t ARM_BOOT_ARCH; + uint8_t FADT_minjor_version; + + // there used in 64bits address mode + uint64_t *X_FIREWARE_CTRL; + uint64_t *X_DSDT; + acpi_address_t X_PM1a_EVT_BLK; + acpi_address_t X_PM1b_EVT_BLK; + acpi_address_t X_PM1a_CNT_BLK; + acpi_address_t X_PM1b_CNT_BLK; + acpi_address_t X_PM2_CNT_BLK; + acpi_address_t X_PM_TMR_BLK; + acpi_address_t X_GPE0_BLK; + acpi_address_t X_GPE1_BLK; + acpi_address_t SLEEP_CONTROL_REG; + acpi_address_t SLEEP_STATUS_REG; + uint8_t hypervisor_vendor_id; +} acpi_facp_t; +#pragma pack(pop) + +#pragma pack(push, 1) +typedef struct +{ + uint8_t sign[4]; // string 'APIC' + uint32_t len; + uint8_t revision; + uint8_t chksum; + uint8_t oemid[6]; + uint8_t oemtableid[8]; + uint8_t oemrevision[4]; + uint8_t create_id[4]; + uint8_t create_revision[4]; + uint32_t local_apic; // local apic address + uint32_t flags; // flags =1 install DUAL PIC hardware +} acpi_madt_t; +#pragma pack(pop) + +#pragma pack(push, 1) +typedef struct +{ + uint8_t ioapic_id; + uint8_t reserved; + uint32_t ioapic_base; // iobase base + uint32_t gsi_base; +} madt_ioapic_entry_t; +#pragma pack(pop) + +#pragma pack(push, 1) +typedef struct +{ + uint8_t bus; + uint8_t irq; + uint32_t gsi; + uint16_t flags; +} madt_ioapic_int_assert_t; +#pragma pack(pop) + +#pragma pack(push, 1) +typedef struct +{ + uint8_t nmi; + uint8_t reserved; + uint16_t flags; + uint32_t gsi; +} madt_ioapic_nmi_assert_t; +#pragma pack(pop) + +typedef enum +{ + MADT_PROCESSOR_LOCAL_APIC = 0, + MADT_PRCESSOR_IOAPIC = 1, + MADT_LOCAL_INT_ASSERT = 2, + MADT_LOCAL_NMI_ASSERT = 3, +} madt_entry_t; + +#pragma pack(push, 1) +typedef struct +{ + uint8_t ACPI_processorID; + uint8_t APIC_ID; + uint32_t flags; // bit0 = processor enabled bit1 = online capable +} madt_processor_localAPIC_t; +#pragma pack(pop) + +uint8_t *AcpiGetRSDPtr(); +int AcpiCheckHeader(void *ptr, uint8_t *sign); +uint8_t *AcpiCheckRSDPtr(void *ptr); +uint32_t AcpiGetMadtBase(); +void power_off(); +void power_reset(); +int acpi_enable(); +int acpi_disable(); +void acpi_install(); + +#endif //CRASHPOWEROS_ACPI_H diff --git a/include/shell.h b/include/shell.h index f6b66b5..caec84d 100644 --- a/include/shell.h +++ b/include/shell.h @@ -18,5 +18,6 @@ void cmd_mkdir(int argc, char **argv); void cmd_read(int argc, char **argv); void cmd_cat(int argc, char **argv); void cmd_ls(); +void cmd_shutdown(); #endif //CRASHPOWEROS_SHELL_H diff --git a/include/task.h b/include/task.h index 0c88ff8..509f61d 100644 --- a/include/task.h +++ b/include/task.h @@ -28,7 +28,7 @@ struct task_struct { char *name; // 进程名 void *stack; // 进程的内核栈地址 page_directory_t *pgd_dir; // 进程页表 - struct context context; // 进程切换需要的上下文信息 + struct context context; // 上下文信息 struct task_struct *next; // 链表指针 }; @@ -46,4 +46,6 @@ void change_task_to(struct task_struct *next); void task_kill(int pid); +void kill_all_task(); + #endif //CRASHPOWEROS_TASK_H diff --git a/kernel/kernel.c b/kernel/kernel.c index e5144d4..cfff365 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -10,19 +10,24 @@ #include "../include/keyboard.h" #include "../include/shell.h" #include "../include/date.h" +#include "../include/acpi.h" extern uint32_t end; extern int status; uint32_t placement_address = (uint32_t) & end; void reset_kernel(){ - printf("Restart %s for x86...",OS_NAME); + printf("Restart %s for x86...\n",OS_NAME); + kill_all_task(); clock_sleep(10); - outb(0x64,0xfe); + power_reset(); } void shutdown_kernel(){ - //TODO ACPI Driver + printf("Shutdown %s for x86...\n",OS_NAME); + kill_all_task(); + clock_sleep(10); + power_off(); } void kernel_main(multiboot_t *multiboot) { @@ -40,10 +45,12 @@ void kernel_main(multiboot_t *multiboot) { idt_install(); printf("[\035kernel\036]: description table config success!\n"); init_timer(10); + acpi_install(); + printf("[\035kernel\036]: ACPI enable success!\n"); init_page(); printf("[\035kernel\036]: page set success!\n"); init_sched(); - printf("[\035kernel\036]: PCB load success!\n"); + printf("[\035kernel\036]: task load success!\n"); init_keyboard(); printf("[\035kernel\036]: Keyboard driver load success!\n"); diff --git a/kernel/task.c b/kernel/task.c index 8c43975..f49cda2 100644 --- a/kernel/task.c +++ b/kernel/task.c @@ -1,6 +1,7 @@ #include "../include/task.h" #include "../include/common.h" #include "../include/graphics.h" +#include "../include/io.h" struct task_struct *running_proc_head = NULL; struct task_struct *wait_proc_head = NULL; @@ -111,7 +112,8 @@ void task_kill(int pid){ break; } printf("Task [%s] exit code: -130.\n",argv->name); - + io_sti(); + kfree(argv); struct task_struct *head = running_proc_head; struct task_struct *last = NULL; while (1){ @@ -122,6 +124,7 @@ void task_kill(int pid){ last = head; head = head->next; } + io_cli(); } void schedule() { @@ -137,6 +140,7 @@ void change_task_to(struct task_struct *next) { //switch_page_directory(current->pgd_dir); switch_to(&(prev->context), &(current->context)); + } } @@ -185,6 +189,18 @@ void kthread_exit() { while (1); } +void kill_all_task(){ + struct task_struct *head = running_proc_head; + while (1){ + head = head->next; + if(head == NULL || head->pid == running_proc_head->pid){ + return; + } + if(head->pid == current->pid) continue; + task_kill(head->pid); + } +} + void init_sched() { // 为当前执行流创建信息结构体 该结构位于当前执行流的栈最低端 current = (struct task_struct *) kmalloc(sizeof(struct task_struct)); diff --git a/sysapp/shell.c b/sysapp/shell.c index a488b39..3cacda3 100644 --- a/sysapp/shell.c +++ b/sysapp/shell.c @@ -184,6 +184,10 @@ void cmd_reset(){ reset_kernel(); } +void cmd_shutdown(){ + shutdown_kernel(); +} + void setup_shell(){ vga_clear(); printf("%s for x86 [Version %s] \n",OS_NAME, OS_VERSION); @@ -225,6 +229,8 @@ void setup_shell(){ cmd_del(argc, argv); else if (!strcmp("reset", argv[0])) cmd_reset(); + else if (!strcmp("shutdown", argv[0])||!strcmp("exit", argv[0])) + cmd_shutdown(); else if (!strcmp("help", argv[0]) || !strcmp("?", argv[0]) || !strcmp("h", argv[0])) { vga_writestring("-=[\037CrashPowerShell Helper\036]=-\n"); vga_writestring("help ? h \032Print shell help info.\036\n"); @@ -238,6 +244,7 @@ void setup_shell(){ vga_writestring("sysinfo \032Print system info.\036\n"); vga_writestring("proc [kill|list] \032Lists all running processes.\036\n"); vga_writestring("reset \032Reset OS.\036\n"); + vga_writestring("shutdown exit \032Shutdown OS.\036\n"); } else printf("\033[Shell]: Unknown command '%s'.\036\n", argv[0]); } }