Skip to content

Commit

Permalink
EFI-enabled graphics initialization
Browse files Browse the repository at this point in the history
  • Loading branch information
portasynthinca3 committed Dec 22, 2019
1 parent c11af78 commit d0affe3
Show file tree
Hide file tree
Showing 8 changed files with 152 additions and 68 deletions.
Binary file modified build/neutron.img
Binary file not shown.
2 changes: 1 addition & 1 deletion builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def get_c_files(dir_name):

print('Bulding system image')
print(' Creating image file')
os.system('dd if=/dev/zero of=build/neutron.img count=' + str(image_size_sectors) + ' > /dev/null')
os.system('dd if=/dev/zero of=build/neutron.img count=' + str(image_size_sectors) + ' > /dev/null 2>&1')
os.system('mformat -i build/neutron.img -f ' + str(image_size_sectors / 2))
print(' Creating filesystem')
os.system('mmd -i build/neutron.img ::/EFI')
Expand Down
1 change: 0 additions & 1 deletion neutron.nbuild
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
.c
src/quark.c
src/isr_wrapper.s
src/a20.s
src/stdlib.c

src/gui/gui.c
Expand Down
41 changes: 0 additions & 41 deletions src/a20.s

This file was deleted.

139 changes: 132 additions & 7 deletions src/drivers/gfx.c
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
//Neutron Project
//Kernel graphics driver

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

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

EFI_SYSTEM_TABLE* quark_get_efi_systable(void);

//The video buffer pointers
color32_t* vbe_buffer;
color32_t* sec_buffer;
Expand All @@ -16,6 +22,8 @@ const uint8_t* font;
uint8_t buf_sel;
//Is gfx_verbose_println() enabled or not?
uint8_t verbose_enabled;
//Pointer to the graphics output protocol
EFI_GRAPHICS_OUTPUT_PROTOCOL* graphics_output;

/*
* Retrieve the horizontal resolution
Expand All @@ -42,14 +50,131 @@ color32_t* gfx_buffer(void){
* Initialize the graphics driver
*/
void gfx_init(void){
//Read the VBE buffer pointer (it was written in memory by the second stage loader)
vbe_buffer = (color32_t*)(*(uint64_t*)(0x8FC00UL));
//Read the display resolution
uint32_t res = *(uint32_t*)(0x8FC04);
res_y = res & 0xFFFF;
res_x = (res >> 16) & 0xFFFF;
//Find the graphics output protocol
gfx_find_gop();
//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");
while(1);
} else {
quark_get_efi_systable()->ConOut->OutputString(quark_get_efi_systable()->ConOut,
(CHAR16*)L"GOP found\r\n");
}
//Choose the best video mode
gfx_choose_best();
//Retrieve its parameters
res_x = graphics_output->Mode->Info->HorizontalResolution;
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));
}

/*
* Finds the EFI Graphics Output Protocol
*/
void gfx_find_gop(void){
//Set the GOP to NULL
graphics_output = NULL;
//Handle the graphics output protocol
//Firstly, through the ConsoleOut handle
EFI_STATUS status;
status = quark_get_efi_systable()->BootServices->HandleProtocol(quark_get_efi_systable()->ConsoleOutHandle,
&((EFI_GUID)EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID), (void**)&graphics_output);
if(!EFI_ERROR(status))
return;
//Then, directly
status = quark_get_efi_systable()->BootServices->LocateProtocol(&((EFI_GUID)EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID),
NULL, (void**)graphics_output);
if(!EFI_ERROR(status))
return;
//Lastly, locate by handle
uint64_t handle_count = 0;
EFI_HANDLE* handle;
status = quark_get_efi_systable()->BootServices->LocateHandleBuffer(ByProtocol,
&((EFI_GUID)EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID), NULL, &handle_count, &handle);
if(EFI_ERROR(status))
return;
status = quark_get_efi_systable()->BootServices->HandleProtocol(handle,
&((EFI_GUID)EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID), (void*)&graphics_output);
}

/*
* Chooses the best available video mode
*/
void gfx_choose_best(void){
EFI_STATUS status;

quark_get_efi_systable()->ConOut->OutputString(quark_get_efi_systable()->ConOut,
(CHAR16*)L"Probing video mode list\r\n");

//Get the EDID
uint64_t handle_count = 0;
EFI_HANDLE* handle;
EFI_EDID_DISCOVERED_PROTOCOL* edid;
status = quark_get_efi_systable()->BootServices->LocateHandleBuffer(ByProtocol,
&((EFI_GUID)EFI_EDID_DISCOVERED_PROTOCOL_GUID), NULL, &handle_count, &handle);
if(EFI_ERROR(status)){
quark_get_efi_systable()->ConOut->OutputString(quark_get_efi_systable()->ConOut,
(CHAR16*)L"Error: unable to find EDID protocol handle\r\n");
while(1);
}
status = quark_get_efi_systable()->BootServices->HandleProtocol(handle,
&((EFI_GUID)EFI_EDID_DISCOVERED_PROTOCOL_GUID), (void*)&edid);
//Parse it
//To be specific, its detailed timing descriptors
uint32_t mon_best_res_x;
uint32_t mon_best_res_y;
//Go through advanced timing descriptors
for(uint32_t base = 54; base <= 108; base += 18){
uint32_t mon_res_x = *(uint8_t* volatile)(edid->Edid + base + 2) << 4;
uint32_t mon_res_y = *(uint8_t* volatile)(edid->Edid + base + 5) << 4;
if(mon_res_x > mon_best_res_x || mon_res_y > mon_best_res_y){
mon_best_res_x = mon_res_x;
mon_best_res_y = mon_res_y;
}
}

EFI_GRAPHICS_OUTPUT_MODE_INFORMATION* mode_info;
uint64_t mode_info_size;
uint32_t best_res_x;
uint32_t best_res_y;
uint32_t best_mode_num;
//Go through each mode and query its properties
for(uint32_t i = 0; i < graphics_output->Mode->MaxMode; i++){
//Query mode information
status = graphics_output->QueryMode(graphics_output, i, &mode_info_size, &mode_info);
//If we encounter an error
if(EFI_ERROR(status)){
//If the error is "not started"
if(status == EFI_NOT_STARTED){
//Start it and query mode info once again
status = graphics_output->SetMode(graphics_output, graphics_output->Mode->Mode);
status = graphics_output->QueryMode(graphics_output, i, &mode_info_size, &mode_info);
} else {
//In case of any other error, skip this mode
continue;
}
}

//Only choose BGRReserved modes
if(mode_info->PixelFormat == PixelBlueGreenRedReserved8BitPerColor){
//Fetch mode resolution and compare it with the best one currently discovered
//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*/){
//Record the new best mode
best_res_y = mode_res_y;
best_res_x = mode_res_x;
best_mode_num = i;
}
}
}
//Set the mode
graphics_output->SetMode(graphics_output, best_mode_num);
}

/*
Expand Down
2 changes: 2 additions & 0 deletions src/drivers/gfx.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ uint32_t gfx_res_y(void);
color32_t* gfx_buffer(void);

void gfx_init(void);
void gfx_find_gop(void);
void gfx_choose_best(void);
void gfx_flip(void);
void gfx_set_font(const unsigned char* fnt);
void gfx_set_buf(unsigned char buf);
Expand Down
28 changes: 17 additions & 11 deletions src/quark.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@ uint8_t quark_verbose;
//Pointer to the EFI system table
EFI_SYSTEM_TABLE* quark_efi_systable;

/*
* Gets the EFI system table
*/
EFI_SYSTEM_TABLE* quark_get_efi_systable(void){
return quark_efi_systable;
}

/*
* This function is called whenever the user chooses the system color
*/
Expand Down Expand Up @@ -110,7 +117,7 @@ void quark_boot_status(char* str, uint32_t progress){
(p2d_t){.x = gfx_res_x() / 3, .y = 2}, COLOR32(255, 64, 64, 64));
gfx_draw_filled_rect((p2d_t){.x = gfx_res_x() / 3, .y = gfx_res_y() * 3 / 4},
(p2d_t){.x = gfx_res_x() / 300 * progress, .y = 2}, COLOR32(255, 255, 255, 255));
gfx_flip();
//gfx_flip();
} else {
//If we are, draw print the string using verbose mode
gfx_verbose_println(str);
Expand All @@ -121,28 +128,26 @@ void quark_boot_status(char* str, uint32_t progress){
* The entry point for the kernel
*/
EFI_STATUS EFIAPI efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable){
//Disable the watchdog timer
SystemTable->BootServices->SetWatchdogTimer(0, 0, 0, NULL);
//Save the system table pointer
quark_efi_systable = SystemTable;
//Disable the watchdog timer
quark_efi_systable->BootServices->SetWatchdogTimer(0, 0, 0, NULL);
//Print the boot string
SystemTable->ConOut->OutputString(SystemTable->ConOut, (CHAR16*)L"Neutron (UEFI version) is starting up");
while(1);
quark_efi_systable->ConOut->OutputString(SystemTable->ConOut, (CHAR16*)L"Neutron (UEFI version) is starting up\r\n");

//Disable interrupts
__asm__ volatile("cli");
//Initialize x87 FPU
__asm__ volatile("finit");
//Do some initialization stuff
enable_a20();
dram_init();
//dram_init();

//Set verbose mode
quark_verbose = *(uint8_t*)(0x8FC10);
quark_verbose = 0;
gfx_set_verbose(quark_verbose);

//Initialize PICs
pic_init(32, 40); //Remap IRQs
/*pic_init(32, 40); //Remap IRQs
//Set up IDT
struct idt_entry* idt = (struct idt_entry*)malloc(256 * sizeof(struct idt_entry));
//Set every exception IDT entry using the same pattern
Expand Down Expand Up @@ -182,11 +187,11 @@ EFI_STATUS EFIAPI efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable
//Enable interrupts
__asm__ volatile("sti");
//Enable non-maskable interrupts
outb(0x70, 0);
outb(0x70, 0);*/

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

Expand All @@ -202,6 +207,7 @@ EFI_STATUS EFIAPI efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable
(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);

//Initialize PS/2
quark_boot_status(">>> Initializing PS/2 <<<", 15);
Expand Down
7 changes: 0 additions & 7 deletions src/test.c

This file was deleted.

0 comments on commit d0affe3

Please sign in to comment.