diff --git a/src/Makefile b/src/Makefile index 6e6b5c2..32c8a7a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -9,11 +9,12 @@ BOOT_OBJ := $(addsuffix .o,$(basename $(shell find ./boot -name '*.cc' -o -name DRIVERS_OBJ := $(addsuffix .o,$(basename $(shell find ./drivers -name '*.cc' -o -name '*.S'))) LIBS_OBJ := $(addsuffix .o,$(basename $(shell find ./libs -name '*.cc' -o -name '*.S'))) CORE_OBJ := $(addsuffix .o,$(basename $(shell find ./core -name '*.cc' -o -name '*.S'))) +RES_OBJ := $(addsuffix .o,$(basename $(shell find ./res -type f))) all: $(EXEC) -$(EXEC): boot/boot.o $(BOOT_OBJ) $(DRIVERS_OBJ) $(LIBS_OBJ) $(CORE_OBJ) boucane.o - echo $(BOOT_OBJ) +$(EXEC): boot/boot.o $(BOOT_OBJ) $(DRIVERS_OBJ) $(LIBS_OBJ) $(CORE_OBJ) $(RES_OBJ) boucane.o + echo "Resource: $(RES_OBJ)" $(CC) -n -T $(LD_SCRIPT) -nostdlib -o $@ $^ %.o: %.S @@ -22,6 +23,9 @@ $(EXEC): boot/boot.o $(BOOT_OBJ) $(DRIVERS_OBJ) $(LIBS_OBJ) $(CORE_OBJ) boucane. %.o: %.cc $(CC) -c -o $@ $^ +%.o: %.psf + objcopy -I binary -O elf64-x86-64 --prefix-symbol res $^ $@ + clean: rm -f $(EXEC) find ./ -name "*.o" -delete diff --git a/src/boot/boot.S b/src/boot/boot.S index 029a67e..7f12eed 100644 --- a/src/boot/boot.S +++ b/src/boot/boot.S @@ -35,6 +35,15 @@ mb_header_start: .int 12 .int _start # ----------- End tag +# ----------- Ask framebuffer tag +.align 8 +.short 5 +.short 1 +.int 20 +.int 0 +.int 0 +.int 0 +# ----------- End framebuffer .align 8 .int 0x0 .int 0x8 diff --git a/src/boot/multiboot2.cc b/src/boot/multiboot2.cc index 1b661b8..d1a912d 100644 --- a/src/boot/multiboot2.cc +++ b/src/boot/multiboot2.cc @@ -52,4 +52,13 @@ char mb2_find_old_rsdp(u32* mb2_info_addr, u64 *return_addr, u32 *return_size){ return 1; } return 0; +} + +char mb2_find_framebuffer(u32* mb2_info_addr, FRAMEBUFFER *fb){ + u32* addr=mb2_find_tag(mb2_info_addr,8); + if(addr){ + memcpy(addr, fb, sizeof(FRAMEBUFFER)); + return 1; + } + return 0; } \ No newline at end of file diff --git a/src/boot/multiboot2.hpp b/src/boot/multiboot2.hpp index da12e5f..cc28109 100644 --- a/src/boot/multiboot2.hpp +++ b/src/boot/multiboot2.hpp @@ -2,7 +2,24 @@ #include "core/types.hpp" +typedef struct TAG_HEADER { + u32 type; + u32 size; +}__attribute__((packed)) TAG_HEADER; + +typedef struct FRAMEBUFFER { + TAG_HEADER header; + u64 addr; + u32 pitch; + u32 width; + u32 height; + u8 bpp; + u8 type; + u64 color_info_addr; +} __attribute__((packed)) FRAMEBUFFER; + u32* mb2_find_tag(u32 *mb2_info_addr, char type); char mb2_find_bootloader_name(u32* mb2_info_addr, char *return_name); char mb2_find_new_rsdp(u32* mb2_info_addr, u64 *return_addr, u32 *return_size); -char mb2_find_old_rsdp(u32* mb2_info_addr, u64 *return_addr, u32 *return_size); \ No newline at end of file +char mb2_find_old_rsdp(u32* mb2_info_addr, u64 *return_addr, u32 *return_size); +char mb2_find_framebuffer(u32* mb2_info_addr, FRAMEBUFFER *fb); \ No newline at end of file diff --git a/src/boucane.cc b/src/boucane.cc index 6541902..791c5cc 100644 --- a/src/boucane.cc +++ b/src/boucane.cc @@ -4,21 +4,60 @@ #include "core/paging.hpp" #include "core/apic.hpp" #include "drivers/acpi.hpp" - +#include "drivers/psf.hpp" +#include "drivers/framebuffer.hpp" +#include "libs/stdio.hpp" +#include "core/asm.hpp" extern u32 MB_INFO; +extern u64 res_binary_res_terminus_psf_start; + + + + + + + extern "C" void boucane(){ - clear(); - printk("Booting Boucane v%d.%d.%d\n",VERSION_MAJOR,VERSION_MINOR, VERSION_PATH); - idt_enable_interrupt(); + //clear(); + //printk("Booting Boucane v%d.%d.%d\n",VERSION_MAJOR,VERSION_MINOR, VERSION_PATH); + //idt_enable_interrupt(); paging_enable(); + + FRAMEBUFFER fb_info; + if(mb2_find_framebuffer((u32*)MB_INFO, &fb_info)){ + if(fb_info.bpp>16){ + FB_CFG conf; + conf.depth=fb_info.bpp; + conf.location=fb_info.addr; + conf.pitch=fb_info.pitch; + conf.width=fb_info.width; + conf.height=fb_info.height; + framebuffer_init(conf); + psf_init((void*)&res_binary_res_terminus_psf_start); + __putchar=psf_putchar; + } + } + printk("Booting Boucane v%d.%d.%d\n",VERSION_MAJOR,VERSION_MINOR, VERSION_PATH); + printk("Jean"); + + printk("Loic"); + //framebuffer_clear(); //apic_enable(); - u64 p; +/* u64 p; u32 size; if(mb2_find_old_rsdp((u32*)MB_INFO,&p,&size)){ - acpi_load_madt((void*)p); - } + acpi_init((void*)p); + }*/ + + //FRAMEBUFFER fb; + //if(mb2_find_framebuffer((u32*)MB_INFO, &fb)){ + //printk("Framebuffer found!"); + //framebuffer_init(fb.addr, fb.pitch, fb.bpp); + //__putchar=psf_print; + //printk("Hello"); + //} while(1); } \ No newline at end of file diff --git a/src/core/paging.hpp b/src/core/paging.hpp index 15d04ad..4bb668c 100644 --- a/src/core/paging.hpp +++ b/src/core/paging.hpp @@ -18,6 +18,9 @@ /// @brief Get page address that contain addr #define PAGE(addr) (addr&(~(0xFFF))) +#define PAGING_MAP(addr) paging_allocate_addr(kpml4,(u64)(addr),(u64)(addr),PAGING_OPT_P|PAGING_OPT_RW) + +extern u64* kpml4; /** * Setup and enable PAE paging diff --git a/src/drivers/acpi.cc b/src/drivers/acpi.cc index bb48ba4..9c25202 100644 --- a/src/drivers/acpi.cc +++ b/src/drivers/acpi.cc @@ -1,33 +1,40 @@ #include "acpi.hpp" #include "core/paging.hpp" -#include "drivers/framebuffer.hpp" #include "libs/stdio.hpp" #include "libs/string.hpp" -// TODO: ALL! +RSDP rsdp; +RSDT rsdt; +IOAPIC ioapic; +char acpi_init(void* rsdp_p){ + printk("Init ACPI... "); -char acpi_load_madt(void* rsdp_p){ // Load RSDP - RSDP rsdp; memcpy(rsdp_p, &rsdp, sizeof(rsdp)); if(rsdp.signature!=ACPI_RSDP_SIGNATURE){ printk("Invalid RSDP signature\n"); return 1; } if(acpi_checksum(rsdp_p, 20)){ - printk("Wrong RSDP Signature\n\n"); + printk("Wrong RSDP Signature\n"); return 1; } - printk("ACPI Revision %d detected!\n",rsdp.revision); + printk("ACPI Revision %d detected. ",rsdp.revision); - // Load RSDT - RSDT rsdt; + // Load sub tables + if(acpi_load_rsdt()) + return 1; + if(acpi_load_madt()) + return 1; + print("\n"); + return 0; +} - paging_allocate_addr(kpml4,(u64)rsdp.rsdt_addr,(u64)rsdp.rsdt_addr,PAGING_OPT_P|PAGING_OPT_RW); +char acpi_load_rsdt(){ + PAGING_MAP(rsdp.rsdt_addr); // Ensure page is accessible memcpy((void*)rsdp.rsdt_addr, &rsdt, sizeof(rsdt)); rsdt.first_entry_addr_ptr=rsdp.rsdt_addr+36; - if(rsdt.header.signature !=ACPI_RSDT_SIGNATURE){ printk("Invalid RSDT signature\n"); return 1; @@ -36,22 +43,38 @@ char acpi_load_madt(void* rsdp_p){ printk("Wrong RSDT Signature\n"); return 1; } + printk("RSDT loaded. "); + return 0; +} +char acpi_load_madt(){ + int n_entry=(rsdt.header.length-36)/4; // Locate MADT - for(int i=0;i<10;i++){ + for(int i=0;i<n_entry;i++){ u32 *addr=(u32*)(rsdt.first_entry_addr_ptr+i*4); - u64 header_p_i=*addr; + // Load header ACPI_TABLE_HEADER header; - paging_allocate_addr(kpml4,header_p_i,header_p_i,PAGING_OPT_P|PAGING_OPT_RW); - memcpy((void*)header_p_i, &header, sizeof(header)); + PAGING_MAP(*addr); + memcpy((void*)*addr, &header, sizeof(header)); + // Check if it is MADT if(header.signature==ACPI_MADT_SIGNATURE){ - printk("MADT found!"); + printk("MADT found. "); + int int_ctrl_location=0; + while(int_ctrl_location<(header.length-44)){ + u32 cur_addr=(*addr)+44+int_ctrl_location; + INT_CTRL_HEADER int_header; + memcpy((void*)cur_addr, &int_header, sizeof(int_header)); + if(int_header.type==1){ + printk("APIC Detected."); + memcpy((void*)cur_addr, &ioapic, sizeof(ioapic)); + return 0; + } + int_ctrl_location+=int_header.length; + } + } } - - - - return 0; + return 1; } char acpi_checksum(void* p, char size){ diff --git a/src/drivers/acpi.hpp b/src/drivers/acpi.hpp index 7bbcdb0..15374d8 100644 --- a/src/drivers/acpi.hpp +++ b/src/drivers/acpi.hpp @@ -37,7 +37,21 @@ typedef struct INT_CTRL_HEADER { u8 length; } __attribute__((packed)) INT_CTRL_HEADER; +typedef struct IOAPIC { + INT_CTRL_HEADER header; + u8 ioapic_id; + u8 reserved; + u32 ioapic_addr; + u32 global_system_interrupt_base; +} __attribute__((packed)) IOAPIC; + + +extern RSDP rsdp; +extern RSDT rsdt; +extern IOAPIC ioapic; -char acpi_load_madt(void* rsdp_p); char acpi_checksum(void* p, char size); +char acpi_load_rsdt(); +char acpi_load_madt(); +char acpi_init(void* rsdp_p); diff --git a/src/drivers/framebuffer.cc b/src/drivers/framebuffer.cc index 2fbe153..2ac47db 100644 --- a/src/drivers/framebuffer.cc +++ b/src/drivers/framebuffer.cc @@ -1,58 +1,30 @@ #include "framebuffer.hpp" +#include "core/paging.hpp" +#include "libs/string.hpp" -#define MAX_COL 80 -#define MAX_LINE 25 +FB_CFG fb_cfg; -VIDEO_STATE VS={ - (u8 *)0xB8000, - 0, - 0, - BLACK, - GRAY, -}; -void putchar(char c){ - // Handle newline here - if(c=='\n'){ - VS.col=0; - VS.line+=1; - if(VS.line>=MAX_LINE){ - VS.line=MAX_LINE-1; - scrollup(); - } - return; - } - - // Print char - VS.mem[VS.col*2+MAX_COL*VS.line*2]=c; - VS.mem[VS.col*2+MAX_COL*VS.line*2+1]=VS.fg|VS.bg<<4; - - // Refresh location - VS.col+=1; - if(VS.col>= MAX_COL){ - VS.col=0; - VS.line+=1; - if(VS.line>=MAX_LINE){ - VS.line=MAX_LINE-1; - scrollup(); - } - } +void framebuffer_init(FB_CFG config){ + fb_cfg=config; } -void clear(){ - for(u8 i=0;i<MAX_LINE;i++){ - scrollup(); - } +void framebuffer_draw(FB_PIXEL p){ + u8 *pixel=(u8*)(fb_cfg.location+p.x*(fb_cfg.depth/8)+p.y*fb_cfg.pitch); + PAGING_MAP(pixel); + pixel[0]=p.r; + pixel[1]=p.g; + pixel[2]=p.b; + if(fb_cfg.depth==32) + pixel[3]=p.a; } -void scrollup(){ - // Move VS.line up - for(u8 i=1;i<=MAX_LINE;i++){ - for(u8 j=0;j<=MAX_COL;j++) - VS.mem[j*2+MAX_COL*(i-1)*2]=VS.mem[j*2+MAX_COL*i*2]; - } - // Clear last VS.line - for(u8 i=0;i<=MAX_COL;i++){ - VS.mem[i*2+MAX_COL*(MAX_LINE-1)*2]='\0'; - } +void framebuffer_scrollup(u32 npixel){ + u64 start=fb_cfg.location+npixel*fb_cfg.pitch; + u64 amount=fb_cfg.pitch*(fb_cfg.height-npixel); + memcpy((void*)start,(void*)fb_cfg.location,amount); } + +void framebuffer_clear(){ + memset((void*)fb_cfg.location, 0, fb_cfg.pitch*fb_cfg.height); +} \ No newline at end of file diff --git a/src/drivers/framebuffer.hpp b/src/drivers/framebuffer.hpp index fb09d6f..958a44b 100644 --- a/src/drivers/framebuffer.hpp +++ b/src/drivers/framebuffer.hpp @@ -1,33 +1,26 @@ #pragma once -#include "core/types.hpp" +#include "include/boucane.hpp" -typedef enum VIDEO_COLORS { - BLACK=0, BLUE=1, GREEN=2,CYAN=3, RED=4,PURPLE=5,BROWN=6,GRAY=7, - DARK_GRAY=8,LIGHT_BLUE=9,LIGHT_GREEN=10,LIGHT_CYAN=11,LIGHT_RED=12,LIGHT_PURPLE=13,YELLOW=14,WHITE=15 - -} VIDEO_COLORS; +typedef struct { + u32 pitch; + u32 depth; + u64 location; + u32 width; + u32 height; +} __attribute__((packed)) FB_CFG; -typedef struct VIDEO_STATE { - u8 *mem; - u8 col; - u8 line; - u8 bg; - u8 fg; -} VIDEO_STATE; +typedef struct { + u32 x,y; + u8 r,g,b,a; +} __attribute__((packed)) FB_PIXEL; -/** - * Print char - */ -void putchar(char); +extern FB_CFG fb_cfg; -/** - * Scroll the framebuffer from one line - */ -void scrollup(); +void framebuffer_init(FB_CFG config); -/** - * Clear all char from the framebuffer - */ -void clear(); +void framebuffer_draw(FB_PIXEL p); +void framebuffer_scrollup(u32 npixel); + +void framebuffer_clear(); \ No newline at end of file diff --git a/src/drivers/psf.cc b/src/drivers/psf.cc new file mode 100644 index 0000000..187d711 --- /dev/null +++ b/src/drivers/psf.cc @@ -0,0 +1,67 @@ +#include "psf.hpp" +#include "core/paging.hpp" +#include "libs/string.hpp" +#include "drivers/framebuffer.hpp" + +PSF_STATUS psf_status; + +void psf_init(void* psf_addr){ + printk("Loading PSF font... "); + memcpy(psf_addr, &psf_status.header, sizeof(PSF_HEADER)); + if(psf_status.header.magic!=PSF_MAGIC){ + printk("Invalid PSF magic number. Abort.\n"); + return; + } + + printk("Flags %d Version %d Glyphs number %d Size %dx%d", + psf_status.header.flags, psf_status.header.version, + psf_status.header.glyph_count, psf_status.header.glyph_width, psf_status.header.glyph_height); + psf_status.x=0; + psf_status.y=0; + psf_status.psf_addr=(u8*)psf_addr; + psf_status.nline=fb_cfg.height/psf_status.header.glyph_height; + psf_status.nchar=fb_cfg.width/psf_status.header.glyph_width; + psf_status.bg=0; + psf_status.fg=200; + print("\n"); +} + +void psf_putchar(char c){ + if(c=='\n'){ + psf_status.y++; + psf_status.x=0; + if(psf_status.y>psf_status.nline) + framebuffer_scrollup(psf_status.header.glyph_height); + return; + } + + u8* glyph=(psf_status.psf_addr+psf_status.header.header_length+c*psf_status.header.glyph_size); + FB_PIXEL pixel; + for(int i=0;i<psf_status.header.glyph_height;i++){ + PAGING_MAP(glyph); + for(int k=0;k<(psf_status.header.glyph_width/8);k++){ + u8 mask=1<<7; + u8 row=*(glyph+k); + for(int j=0;j<8;j++){ + u16 status=row&mask; + u8 color=status ? psf_status.fg:psf_status.bg; + pixel.x=j+k*8+psf_status.x*psf_status.header.glyph_width; + pixel.y=i+psf_status.y*psf_status.header.glyph_height; + pixel.r=color; + pixel.g=color; + pixel.b=color; + pixel.a=color; + framebuffer_draw(pixel); + mask>>=1; + } + } + glyph+=psf_status.header.glyph_width/8; + } + psf_status.x++; + if(psf_status.x>psf_status.nchar){ + psf_status.y++; + psf_status.x=0; + if(psf_status.y>psf_status.nline) + framebuffer_scrollup(psf_status.header.glyph_height); + } +} \ No newline at end of file diff --git a/src/drivers/psf.hpp b/src/drivers/psf.hpp new file mode 100644 index 0000000..1163dee --- /dev/null +++ b/src/drivers/psf.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include "include/boucane.hpp" + +#define PSF_MAGIC 0x864ab572 + +typedef struct PSF_HEADER { + u32 magic; + u32 version; + u32 header_length; + u32 flags; + u32 glyph_count; + u32 glyph_size; + u32 glyph_height; + u32 glyph_width; +} __attribute__((packed)) PSF_HEADER; + +typedef struct PSF_STATUS { + PSF_HEADER header; + u32 x,y; + u32 nline; + u32 nchar; + u8 bg,fg; + u8* psf_addr; +} __attribute__((packed)) PSF_STATUS; + + +extern PSF_HEADER psf_header; + +void psf_init(void* psf_addr); +void psf_putchar(char c); \ No newline at end of file diff --git a/src/drivers/vga_t.cc b/src/drivers/vga_t.cc new file mode 100644 index 0000000..6e50b40 --- /dev/null +++ b/src/drivers/vga_t.cc @@ -0,0 +1,58 @@ +#include "vga_t.hpp" + +#define MAX_COL 80 +#define MAX_LINE 25 + +VIDEO_STATE VS={ + (u8 *)0xB8000, + 0, + 0, + BLACK, + GRAY, +}; + +void vga_t_putchar(char c){ + // Handle newline here + if(c=='\n'){ + VS.col=0; + VS.line+=1; + if(VS.line>=MAX_LINE){ + VS.line=MAX_LINE-1; + vga_t_scrollup(); + } + return; + } + + // Print char + VS.mem[VS.col*2+MAX_COL*VS.line*2]=c; + VS.mem[VS.col*2+MAX_COL*VS.line*2+1]=VS.fg|VS.bg<<4; + + // Refresh location + VS.col+=1; + if(VS.col>= MAX_COL){ + VS.col=0; + VS.line+=1; + if(VS.line>=MAX_LINE){ + VS.line=MAX_LINE-1; + vga_t_scrollup(); + } + } +} + +void clear(){ + for(u8 i=0;i<MAX_LINE;i++){ + vga_t_scrollup(); + } +} + +void vga_t_scrollup(){ + // Move VS.line up + for(u8 i=1;i<=MAX_LINE;i++){ + for(u8 j=0;j<=MAX_COL;j++) + VS.mem[j*2+MAX_COL*(i-1)*2]=VS.mem[j*2+MAX_COL*i*2]; + } + // Clear last VS.line + for(u8 i=0;i<=MAX_COL;i++){ + VS.mem[i*2+MAX_COL*(MAX_LINE-1)*2]='\0'; + } +} diff --git a/src/drivers/vga_t.hpp b/src/drivers/vga_t.hpp new file mode 100644 index 0000000..dd947bd --- /dev/null +++ b/src/drivers/vga_t.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include "core/types.hpp" + +typedef enum VIDEO_COLORS { + BLACK=0, BLUE=1, GREEN=2,CYAN=3, RED=4,PURPLE=5,BROWN=6,GRAY=7, + DARK_GRAY=8,LIGHT_BLUE=9,LIGHT_GREEN=10,LIGHT_CYAN=11,LIGHT_RED=12,LIGHT_PURPLE=13,YELLOW=14,WHITE=15 + +} VIDEO_COLORS; + +typedef struct VIDEO_STATE { + u8 *mem; + u8 col; + u8 line; + u8 bg; + u8 fg; +} VIDEO_STATE; + +/** + * Print char + */ +void vga_t_putchar(char); + +/** + * Scroll the framebuffer from one line + */ +void vga_t_scrollup(); + +/** + * Clear all char from the framebuffer + */ +void vga_t_clear(); + diff --git a/src/libs/stdio.cc b/src/libs/stdio.cc index 8dcb1f6..dc9ee75 100644 --- a/src/libs/stdio.cc +++ b/src/libs/stdio.cc @@ -1,10 +1,9 @@ #include "stdio.hpp" -#include "drivers/framebuffer.hpp" +#include "drivers/vga_t.hpp" #include "math.hpp" #include "string.hpp" -extern VIDEO_STATE VS; -void (*__putchar)(char)=putchar; +void (*__putchar)(char)=vga_t_putchar; void printk(char *str,...) { u64 rsi,rdx,rcx,r8,r9; diff --git a/src/libs/stdio.hpp b/src/libs/stdio.hpp index 2d252b6..1fbc80a 100644 --- a/src/libs/stdio.hpp +++ b/src/libs/stdio.hpp @@ -1,6 +1,6 @@ #pragma once -#include "drivers/framebuffer.hpp" +#include "drivers/vga_t.hpp" /// @brief Current active framebuffer driver extern void (*__putchar)(char); diff --git a/src/libs/string.cc b/src/libs/string.cc index 8253526..379a128 100644 --- a/src/libs/string.cc +++ b/src/libs/string.cc @@ -1,11 +1,15 @@ #include "string.hpp" +#include "core/paging.hpp" #include "math.hpp" -void memcpy(void* src, void* dst, u32 size){ +void memcpy(void* src, void* dst, u64 size){ u8 *c_src=(u8*)src; u8 *c_dst=(u8*)dst; - for(u32 i=0;i<size;i++) + for(u64 i=0;i<size;i++){ + PAGING_MAP((c_dst+i)); + PAGING_MAP((c_src+i)); *(c_dst+i)=*(c_src+i); + } } void memset(void *dst, char value, u64 size){ diff --git a/src/libs/string.hpp b/src/libs/string.hpp index 74bebc0..c746c47 100644 --- a/src/libs/string.hpp +++ b/src/libs/string.hpp @@ -5,7 +5,7 @@ /** * Copy data byte per byte from src to dst */ -void memcpy(void *src, void *dst, u32 size); +void memcpy(void *src, void *dst, u64 size); void memset(void *dst, char value, u64 size); diff --git a/src/res/terminus.psf b/src/res/terminus.psf new file mode 100644 index 0000000..e7740af Binary files /dev/null and b/src/res/terminus.psf differ