Skip to content

Commit

Permalink
Make the system fuly UEFI-compatible; interrupts still need to be done
Browse files Browse the repository at this point in the history
  • Loading branch information
portasynthinca3 committed Dec 22, 2019
1 parent d0affe3 commit 7832665
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 79 deletions.
Binary file modified build/neutron.img
Binary file not shown.
25 changes: 15 additions & 10 deletions src/drivers/acpi.c
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
//Neutron project
//ACPI driver

#include <efi.h>
#include <efilib.h>

#include "./acpi.h"
#include "./pit.h"
#include "../stdlib.h"
#include "./gfx.h"

EFI_SYSTEM_TABLE* quark_get_efi_systable(void);

uint32_t acpi_smi_cmd;
uint8_t acpi_en;
uint8_t acpi_dis;
Expand All @@ -21,7 +26,6 @@ uint8_t acpi_pm1_ctl_len;
* Initializes ACPI
*/
uint32_t acpi_init(void){
gfx_verbose_println("Initializing ACPI");
//Find the RSDP
acpi_rsdp_t* rsdp = acpi_find_rsdp();
//If no RSDP was found, return
Expand All @@ -31,7 +35,7 @@ uint32_t acpi_init(void){
}

//Fetch RSDT from RSDP
acpi_rsdt_t* rsdt = (acpi_rsdt_t*)rsdp->rsdt_ptr;
acpi_rsdt_t* rsdt = (acpi_rsdt_t*)(uint64_t)rsdp->rsdt_ptr;
//Check if it's valid
if(!acpi_sdt_checksum(&rsdt->hdr)){
gfx_verbose_println("Error: RSDP is not valid");
Expand Down Expand Up @@ -93,6 +97,7 @@ uint32_t acpi_init(void){
gfx_verbose_println("Sending enable commands (this might take a while)");
//Enable ACPI
outb(acpi_smi_cmd, acpi_en);
/*
uint32_t start = pit_ticks();
while((pit_ticks() - start <= 1500) &&
((inw(acpi_pm1a_ctl) & acpi_sci_en) == 0));
Expand All @@ -101,6 +106,7 @@ uint32_t acpi_init(void){
while((pit_ticks() - start <= 1500) &&
((inw(acpi_pm1b_ctl) & acpi_sci_en) == 0));
}
*/

gfx_verbose_println("ACPI successfully initialized");

Expand Down Expand Up @@ -147,14 +153,13 @@ uint8_t acpi_sdt_checksum(acpi_sdt_hdr_t* rsdt){
* Finds ACPI RSDT pointer (RSDP) in memory
*/
acpi_rsdp_t* acpi_find_rsdp(void){
//Go through addresses 0xE0000 - 0xFFFFF
for(void* ptr = (void*)0xE0000; ptr <= (void*)0xFFFFF; ptr++){
//Check the signature
//Note that we use memcmp as the signature is not zero-terminated
if(memcmp(((acpi_rsdp_t*)ptr)->signature, "RSD PTR ", 8) == 0)
return ptr;
//Search for the pointer in the UEFI config table
EFI_CONFIGURATION_TABLE* config_table = quark_get_efi_systable()->ConfigurationTable;
for(uint32_t i = 0; i < quark_get_efi_systable()->NumberOfTableEntries; i++){
//If the GUID is ACPI 1.0 RSDP pointer GUID, return it
if(memcmp(&(config_table[i].VendorGuid), &(EFI_GUID)ACPI_TABLE_GUID, sizeof(EFI_GUID)) == 0)
return config_table[i].VendorTable;
}
//Return null if no RSDP was found
return NULL;
}

Expand All @@ -167,7 +172,7 @@ void* rsdt_find(acpi_rsdt_t* rsdt, char* table){
//Cycle through each entry
for(uint32_t e = 0; e < rsdt_entries; e++){
//Get the SDT header
acpi_sdt_hdr_t* hdr = (acpi_sdt_hdr_t*)(rsdt->ptrs + e);
acpi_sdt_hdr_t* hdr = (acpi_sdt_hdr_t*)(uint64_t)(rsdt->ptrs + e);
//Compare its signature with the desired one
if(*(uint32_t*)(hdr) == *(uint32_t*)(table))
return (void*)hdr;
Expand Down
4 changes: 2 additions & 2 deletions src/drivers/acpi.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ typedef struct {
//ACPI RSDT table
typedef struct {
acpi_sdt_hdr_t hdr;
acpi_sdt_hdr_t** ptrs;
uint32_t ptrs;
} __attribute__((packed)) acpi_rsdt_t;

//ACPI RSDP structure
Expand All @@ -28,7 +28,7 @@ typedef struct {
uint8_t checksum;
char oem[6];
uint8_t rev;
acpi_sdt_hdr_t* rsdt_ptr;
uint32_t rsdt_ptr;
} __attribute__((packed)) acpi_rsdp_t;

//ACPI Generic Address Structure (GAS)
Expand Down
8 changes: 4 additions & 4 deletions src/drivers/gfx.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ void gfx_init(void){
//If it hadn't been found, print an error
if(graphics_output == NULL){
quark_get_efi_systable()->ConOut->OutputString(quark_get_efi_systable()->ConOut,
(CHAR16*)L"Unable to find the graphics output protocol\r\n");
(CHAR16*)L"Error: Unable to find the graphics output protocol\r\n");
while(1);
} else {
quark_get_efi_systable()->ConOut->OutputString(quark_get_efi_systable()->ConOut,
Expand All @@ -68,7 +68,7 @@ void gfx_init(void){
res_y = graphics_output->Mode->Info->VerticalResolution;
vbe_buffer = (color32_t*)graphics_output->Mode->FrameBufferBase;
//Allocate the second buffer based on the screen size
//sec_buffer = (color32_t*)malloc(res_x * res_y * sizeof(color32_t));
sec_buffer = (color32_t*)malloc(res_x * res_y * sizeof(color32_t));
}

/*
Expand Down Expand Up @@ -164,8 +164,8 @@ void gfx_choose_best(void){
//Do not exceed the display resolution
uint32_t mode_res_x = mode_info->HorizontalResolution;
uint32_t mode_res_y = mode_info->VerticalResolution;
if((mode_res_x > best_res_x || mode_res_y > best_res_y)/* &&
mode_res_y <= mon_best_res_y && mode_res_x <= mon_best_res_x*/){
if((mode_res_x > best_res_x || mode_res_y > best_res_y) &&
mode_res_y <= mon_best_res_y && mode_res_x <= mon_best_res_x){
//Record the new best mode
best_res_y = mode_res_y;
best_res_x = mode_res_x;
Expand Down
13 changes: 6 additions & 7 deletions src/quark.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,10 +140,10 @@ EFI_STATUS EFIAPI efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable
//Initialize x87 FPU
__asm__ volatile("finit");
//Do some initialization stuff
//dram_init();
dram_init();

//Set verbose mode
quark_verbose = 0;
quark_verbose = 1;
gfx_set_verbose(quark_verbose);

//Initialize PICs
Expand Down Expand Up @@ -191,7 +191,7 @@ EFI_STATUS EFIAPI efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable

//Do some graphics-related initialization stuff
gfx_init();
gfx_set_buf(GFX_BUF_VBE); //Enable doublebuffering
gfx_set_buf(GFX_BUF_SEC); //Enable doublebuffering
gfx_fill(COLOR32(255, 0, 0, 0));
gfx_set_font(font_neutral);

Expand All @@ -206,8 +206,7 @@ EFI_STATUS EFIAPI efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable
gfx_draw_xbm((p2d_t){.x = (gfx_res_x() - neutron_logo_width) / 2, .y = 50}, neutron_logo_bits,
(p2d_t){.x = neutron_logo_width, .y = neutron_logo_height}, COLOR32(255, 255, 255, 255), COLOR32(255, 0, 0, 0));
//Print the boot process
quark_boot_status(">>> Loading... <<<", 0);
while(1);
quark_boot_status(">>> Loading <<<", 0);

//Initialize PS/2
quark_boot_status(">>> Initializing PS/2 <<<", 15);
Expand All @@ -225,7 +224,7 @@ EFI_STATUS EFIAPI efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable
quark_boot_status(">>> Configuring GUI <<<", 90);
gui_init();
//The loading process is done!
quark_boot_status(">>> Done! <<<", 100);
quark_boot_status(">>> Done <<<", 100);

//Constantly update the GUI
while(1){
Expand All @@ -239,7 +238,7 @@ EFI_STATUS EFIAPI efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable
void quark_exc(void){
//Print some info
unsigned int ip;
__asm__ volatile("mov %0, %%edx" : "=r" (ip));
__asm__ volatile("mov %%edx, %0" : "=r" (ip));
gfx_panic(ip, QUARK_PANIC_CPUEXC_CODE);

//Hang
Expand Down
128 changes: 72 additions & 56 deletions src/stdlib.c
Original file line number Diff line number Diff line change
@@ -1,25 +1,22 @@
//Neutron Project
//C Standard Library

#include <efi.h>
#include <efilib.h>

#include "./stdlib.h"
#include "./drivers/gfx.h"

EFI_SYSTEM_TABLE* quark_get_efi_systable(void);

free_block_t* first_free_block;
void* gen_free_base;
void* gen_free_top;
uint32_t bad_ram_size = 0;
uint64_t bad_ram_size = 0;
uint64_t total_ram_size = 0;
uint32_t usable_ram_size = 0;

uint32_t stdlib_usable_ram(void){
return usable_ram_size;
}

/*
* Trigger bochs magic breakpoint
*/
volatile void breakpoint(){
__asm__("xchgw %bx, %bx;");
return total_ram_size;
}

/*
Expand All @@ -29,57 +26,73 @@ void abort(){
while(1);
}

/*
* Print a string through Bochs's E9 debug port if the port_e9_hack config setting is enabled
*/
void puts_e9(char* str){
char c;
//Fetch the next character
while(c = *(str++))
outb(0xE9, c); //Write it
}

/*
* Initialize the dynamic memory allocator
*/
void dram_init(void){
first_free_block = NULL;
//Parse the memory map
//It was put in memory as a result of a
// collaboration between Muon-2 and BIOS
uint32_t blk_type = 0;
volatile void* volatile block_base = (void*)(0x93C00);
//Keep track of the block with the most size
size_t largest_blk_size = 0;
void* largset_blk_ptr = NULL;
//Type=0 marks the end
while((blk_type = *(uint32_t*)(block_base + 16)) != 0){
//Fetch block base
uint64_t base = *(uint64_t*)(block_base);
//Fetch block length
uint64_t size = *(uint64_t*)(block_base + 8);
//Record the total amount of available RAM
total_ram_size += size;
//Only record the block if it's marked as type 1 (usable RAM)
if(blk_type == 1 && size > 0){
//Only record the block if it stretches over the fifth megabyte
// and its size is larger than the currently found one
if(size + base >= 5 * 1024 * 1024 && size > largest_blk_size){
uint64_t shrink = (5 * 1024 * 1025) - base;
size -= shrink;
largest_blk_size = size;
largset_blk_ptr = (void*)base + shrink;
}
} else if(blk_type == 5){ //Type 5 means bad RAM (used to tell the user)
bad_ram_size += size;
//Get the memory map from EFI
EFI_MEMORY_DESCRIPTOR* buf;
uint64_t desc_size;
uint32_t desc_ver;
uint64_t size, map_key, mapping_size;
EFI_MEMORY_DESCRIPTOR* desc;
EFI_STATUS status;
uint32_t i = 0;
//Allocate some memory
size = sizeof(EFI_MEMORY_DESCRIPTOR) * 31;
mem_map_retry:
size += sizeof(EFI_MEMORY_DESCRIPTOR) * 31;
status = quark_get_efi_systable()->BootServices->AllocatePool(EfiLoaderData, size, (void*)&buf);
if(EFI_ERROR(status)){
quark_get_efi_systable()->ConOut->OutputString(quark_get_efi_systable()->ConOut,
(CHAR16*)L"Failed to allocate memory for the memory map\r\n");
while(1);
}
//Map the memory
status = quark_get_efi_systable()->BootServices->GetMemoryMap(&size, buf, &map_key, &desc_size, &desc_ver);
//Re-allocate the buffer with a different size if the current one isn't sufficient
if(EFI_ERROR(status)){
if(status == EFI_BUFFER_TOO_SMALL){
quark_get_efi_systable()->BootServices->FreePool(buf);
goto mem_map_retry;
} else {
quark_get_efi_systable()->ConOut->OutputString(quark_get_efi_systable()->ConOut,
(CHAR16*)L"Failed to get the memory map\r\n");
while(1);
}
}

desc = buf;
void* best_block_start = NULL;
uint64_t best_block_size = 0;
//Fetch the next descriptor
while((void*)desc < (void*)buf + size){
mapping_size = desc->NumberOfPages * EFI_PAGE_SIZE;

//If a new free memory block was found, record it
if(desc->Type == EfiConventionalMemory && mapping_size > best_block_size){
best_block_size = mapping_size;
best_block_start = (void*)desc->PhysicalStart;
}
//Move on to the next block
block_base += 24;
//Record bad RAM
else if(desc->Type == EfiUnusableMemory){
bad_ram_size += mapping_size;
}

desc = (void*)desc + desc_size;
i++;
}

//Set up general free heap
gen_free_base = best_block_start;
gen_free_top = best_block_start + best_block_size;
total_ram_size += best_block_size;

if(gen_free_top == NULL){
quark_get_efi_systable()->ConOut->OutputString(quark_get_efi_systable()->ConOut,
(CHAR16*)L"No usable memory was found\r\n");
while(1);
}
//Save the information
gen_free_base = largset_blk_ptr;
gen_free_top = largset_blk_ptr + largest_blk_size;
usable_ram_size = largest_blk_size;
}

/*
Expand Down Expand Up @@ -198,10 +211,13 @@ void* memset(void* dst, int ch, size_t size){
*/
void* memcpy(void* destination, const void* source, size_t num){
//We can use the REP MOVx instruction to perform a blazing-fast memory-to-memory data transfer
//Q = 8 bytes at a time
//D = 4 bytes at a time
//W = 2 bytes at a time
//B = 1 byte at a time
if(num % 4 == 0)
if(num % 8 == 0)
__asm__ volatile("rep movsq" : : "D" (destination), "S" (source), "c" (num / 4));
else if(num % 4 == 0)
__asm__ volatile("rep movsd" : : "D" (destination), "S" (source), "c" (num / 4));
else if(num % 2 == 0)
__asm__ volatile("rep movsw" : : "D" (destination), "S" (source), "c" (num / 2));
Expand Down

0 comments on commit 7832665

Please sign in to comment.