uint32_t *mbfb_detect() { uint32_t *fb; uint32_t *legacy_fb = (uint32_t *) 0xA0000; uintptr_t mu,d; physaddr_t t; fb = heapmm_alloc_alligned(mbfb_device_info.fb_size, PHYSMM_PAGE_SIZE); if (!fb) return NULL; legacy_fb[0] = MBFB_SEARCH_MAGIC_1; legacy_fb[1] = MBFB_SEARCH_MAGIC_2; mu = (uintptr_t) fb; for (d = 0; d < mbfb_device_info.fb_size; d += 0x1000) { physmm_free_frame(paging_get_physical_address((void *)(mu + d))); paging_unmap((void *)(mu + d)); } real_fb = 0; for (t = 0xE0000000; t < 0xFF000000; t += 0x1000) { paging_map(fb, t, PAGING_PAGE_FLAG_NOCACHE | PAGING_PAGE_FLAG_RW); if ((fb[0] == MBFB_SEARCH_MAGIC_1) && (fb[1] == MBFB_SEARCH_MAGIC_2)) { debugcon_printf("Found the lfb at %x\n", t); real_fb = t; break; } paging_unmap(fb); } if (!real_fb) { for (d = 0; d < mbfb_device_info.fb_size; d += 0x1000) { t = physmm_alloc_frame(); if (!t) return 0; paging_map((void *)(mu + d), t, PAGING_PAGE_FLAG_RW); } heapmm_free(fb, mbfb_device_info.fb_size); return NULL; } for (d = 0x1000; d < mbfb_device_info.fb_size; d += 0x1000) { paging_map( (void *)(mu + d), real_fb + (physaddr_t) d, PAGING_PAGE_FLAG_NOCACHE | PAGING_PAGE_FLAG_RW); } return fb; }
int lapic_init() { uint32_t edx = 0; cpu_t *cpu = cpu_this; pic_init(); cpu_id(1,NULL,NULL,NULL,&edx); if (edx&(1<<9) && 0) { isr_uselapic = 1; cpu->uselapic = 1; lapic = memkernel_findvirt(1)+PAGEOFF(LAPIC_PHYS_ADDRESS); if (paging_map(PAGEDOWN(lapic),PAGEDOWN(LAPIC_PHYS_ADDRESS),0,1)<0) panic("Cannot map LAPIC\n"); lapic->tpr = 0x20; lapic->lvt_timer = 0x20030; lapic->lvt_thermal = 0x20031; lapic->lvt_pmc = 0x20032; lapic->lvt_lint0 = 0x08700; lapic->lvt_lint1 = 0x08700; lapic->lvt_error = 0x20035; lapic->spurious = 0x0010F; pic_pit_setinterval(0,LAPIC_PIT_CALIBRATE_INTERVAL); return 0; } else { isr_uselapic = 0; cpu->uselapic = 0; cpu->interval = 10; // IRQ0 all 10 ms pic_pit_setinterval(0,cpu->interval); return -1; } }
static void* arch_allocate_pages(size_t numPages) { if (!paging_map(heapaddr, PADDR_T_MAX, numPages*PAGESIZE, PAGE_ATTRIBUTE_WRITABLE)) return nullptr; void* ret = heapaddr; heapaddr = raw_offset<void*>(heapaddr, numPages*PAGESIZE); return ret; }
void paging_handle_fault(void *virt_addr, void * instr_ptr, void *state, size_t state_size, int present, int write, int user) { uintptr_t addr = (uintptr_t) virt_addr; physaddr_t phys_addr; //earlycon_printf("\n PF: 0x%x at IP:0x%x\n", virt_addr, instr_ptr); //debugcon_printf("[0x%x] page fault in %i @ 0x%x (P:%i, W:%i, U:%i) \n", virt_addr, curpid(), instr_ptr, present, user, write); /* Handle page fault here */ if (user && (addr > 0xC0000000)) { //TODO: Dispatch exception, usermode program tried to access kernel space //debugcon_printf("umode violation!"); debugcon_printf("[0x%x] page fault in %i @ 0x%x (P:%i, W:%i, U:%i) \n", virt_addr, curpid(), instr_ptr, present, user, write); exception_handle(EXCEPTION_PAGE_FAULT, instr_ptr, state, state_size); } if (!present) { if ((addr >= 0xBFFF0000) && (addr < 0xBFFFB000)) { /* Task stack area, add more stack */ virt_addr = (void *)(addr & ~PHYSMM_PAGE_ADDRESS_MASK); phys_addr = physmm_alloc_frame(); if (phys_addr == PHYSMM_NO_FRAME) { paging_handle_out_of_memory(); phys_addr = physmm_alloc_frame(); } //TODO: Assess potential for race conditions paging_map(virt_addr, phys_addr, PAGING_PAGE_FLAG_RW | PAGING_PAGE_FLAG_USER); paging_tag(virt_addr, PAGING_PAGE_TAG_USER_DATA); } else if ((addr >= 0xE0000000) && (addr < 0xFFC00000)) { /* Kernel heap, check whether we have previously swapped out this page */ //TODO: Swapping, for now: PANIC!!! //TODO: PANIC! debugcon_printf("[0x%x] page fault in %i @ 0x%x (P:%i, W:%i, U:%i) \n", virt_addr, curpid(), instr_ptr, present, user, write); exception_handle(EXCEPTION_PAGE_FAULT, instr_ptr, state, state_size); } else if (addr < 0xC0000000){ /* Application space page fault */ //TODO: Check for dynamic libraries, mmapped files and swapped out pages //TODO: If no fix was found, dispatch exception if (!procvmm_handle_fault(virt_addr)){ debugcon_printf("[0x%x] page fault in %i @ 0x%x (P:%i, W:%i, U:%i) \n", virt_addr, curpid(), instr_ptr, present, user, write); exception_handle(EXCEPTION_PAGE_FAULT, instr_ptr, state, state_size); } } else { exception_handle(EXCEPTION_PAGE_FAULT, instr_ptr, state, state_size); debugcon_printf("[0x%x] page fault in %i @ 0x%x (P:%i, W:%i, U:%i) \n", virt_addr, curpid(), instr_ptr, present, user, write); } } else if (write) { //TODO: Copy on write, debugcon_printf("[0x%x] page fault in %i @ 0x%x (P:%i, W:%i, U:%i) \n", virt_addr, curpid(), instr_ptr, present, user, write); exception_handle(EXCEPTION_PAGE_FAULT, instr_ptr, state, state_size); } }
size_t heapmm_request_core ( void *address, size_t size ) { size_t size_counter; physaddr_t frame; if (paging_active_dir == NULL) return 0; //debugcon_printf("[0x%x] %i morecore \n", address, size); for (size_counter = 0; size_counter < size; size_counter += PHYSMM_PAGE_SIZE) { frame = physmm_alloc_frame(); if (frame == PHYSMM_NO_FRAME){ debugcon_aputs(" KHEAP:: OUT OF MEM !!!!"); earlycon_aputs(" KHEAP:: OUT OF MEM !!!!"); break; } paging_map(address, frame, PAGING_PAGE_FLAG_RW); paging_tag(address, PAGING_PAGE_TAG_KERNEL_DATA); address = (void *) ( ((uintptr_t) address) + ((uintptr_t) PHYSMM_PAGE_SIZE) ); } return size_counter; }
uint32_t *mbfb_maplfb() { uint32_t *fb; uintptr_t mu,d; fb = heapmm_alloc_alligned(mbfb_device_info.fb_size, PHYSMM_PAGE_SIZE); if (!fb) return NULL; mu = (uintptr_t) fb; for (d = 0; d < mbfb_device_info.fb_size; d += 0x1000) { physmm_free_frame(paging_get_physical_address((void *)(mu + d))); paging_unmap((void *)(mu + d)); } for (d = 0; d < mbfb_device_info.fb_size; d += 0x1000) { paging_map( (void *)(mu + d), real_fb + (physaddr_t) d, PAGING_PAGE_FLAG_NOCACHE | PAGING_PAGE_FLAG_RW); } return fb; }
armv7_l1_table_t *armv7_paging_alloc_l1( void ) { int cont = 1; physaddr_t pa; uintptr_t va, va_ctr; armv7_l1_table_t *l1; /* Allocate a 16K, 16K Alligned chunk of address space */ l1 = heapmm_alloc_alligned( sizeof( armv7_l1_table_t ), sizeof( armv7_l1_table_t ) ); /* Pass out of memory error up the call chain */ if (l1 == NULL) return NULL; /* Get the address */ va = (uintptr_t) l1; /* Check if the block is physically contiguous */ for ( va_ctr = va; va_ctr < (va + sizeof( armv7_l1_table_t )); va_ctr += 4096) { /* If this is the first page, get the physical address */ if ( va_ctr == va ) { pa = paging_get_physical_address ( (void *) va_ctr ); if (pa & 0x3FFF) { cont = 0; break; } } else if (paging_get_physical_address ((void *) va_ctr) != pa ) { /* Frame did not match expected frame */ cont = 0; break; } pa += 4096; } /* If the heap manager gave us a contiguous chunk of memory, accept it*/ if ( cont ) return l1; /* If not, unmap the pages and remap them from a contiguous quad frame*/ /* Unmap the pages */ for ( va_ctr = va; va_ctr < (va + sizeof( armv7_l1_table_t )); va_ctr += 4096) { /* Get the frame to unmap */ pa = paging_get_physical_address ( (void *) va_ctr ); /* Unmap the page */ paging_unmap( (void *) va_ctr ); /* Free the frame */ physmm_free_frame( pa ); } /* Allocate a quadframe */ pa = physmm_alloc_quadframe(); /* Check for out of memory error */ if ( pa == PHYSMM_NO_FRAME ) { paging_handle_out_of_memory(); pa = physmm_alloc_quadframe(); } /* Remap the pages */ for ( va_ctr = va; va_ctr < (va + sizeof( armv7_l1_table_t )); va_ctr += 4096) { /* Map the page */ paging_map( (void *) va_ctr, pa, PAGING_PAGE_FLAG_RW ); /* Get the next of the four frames */ pa += 4096; } /* Return the now contiguous level 1 table */ return l1; }
EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) { InitializeLib(ImageHandle, SystemTable); CallConstructors(); EFI_STATUS Status; const char16_t* searchdir = u"\\EFI\\ChaiOS\\"; if (Status = SetWorkingDirectory(searchdir)) printf(u"Error setting working directory: %s\r\n", getError(Status)); CHAIOS_BOOT_FILES* bootfile = nullptr; while (bootfile = iterateBootFiles(bootfile)) { if (bootfile->loadLocation != nullptr) continue; //Support in-memory images EFI_FILE* file = OpenFile(bootfile->fileName, "r"); if (!file) { printf(u"Error: could not open %s: %s\r\n", bootfile->fileName, getError(getErrno())); } UINT64 fileSize = GetFileSize(file); VOID* bootfilebuf = kmalloc(fileSize+1); UINTN read = ReadFile(bootfilebuf, 1, fileSize, file); if (read < fileSize) printf(u"Read %d bytes, failed\r\n", read); else printf(u"Successfully read %d bytes\r\n", read); //Boot file is now loaded into memory CloseFile(file); bootfile->loadLocation = bootfilebuf; bootfile->fileSize = fileSize; if (bootfile->bootType == CHAIOS_BOOT_CONFIGURATION) { //We need to parse this now. INI format ((char*)bootfilebuf)[fileSize] = '\0'; ini_parse_string((const char*)bootfilebuf, &bootini_handler, nullptr); } } //size_t value = GetIntegerInput(u"Enter scrolling lines configuration: "); //set_scrolllines(value); UINT32 AutoMode = IterateGraphicsMode(&match_config_resoultion); EFI_GRAPHICS_OUTPUT_MODE_INFORMATION* info; UINTN SizeOfInfo; if (AutoMode == UINT32_MAX) { if (!EFI_ERROR(GetGraphicsModeInfo(AutoMode, &info, &SizeOfInfo))) { IterateGraphicsMode(&print_graphics_mode); size_t value = GetIntegerInput(u"Enter boot graphics mode: "); SetGraphicsMode(value); AutoMode = value; } } else { SetGraphicsMode(AutoMode); } if (!EFI_ERROR(GetGraphicsModeInfo(AutoMode, &info, &SizeOfInfo))) { printf(u"Graphics mode %d: %dx%d\r\n", AutoMode, info->HorizontalResolution, info->VerticalResolution); } puts(u"ChaiOS 0.09 UEFI Loader\r\n"); int majorver = SystemTable->Hdr.Revision / (1 << 16); int minorver = SystemTable->Hdr.Revision % (1 << 16); printf(u"Firmware Vendor: %s, version: %d (UEFI:%d.%d)\r\n", SystemTable->FirmwareVendor, SystemTable->FirmwareRevision, majorver, minorver); //Read ACPI configuration tables //startup_acpi(SystemTable); //startup_multiprocessor(); const size_t EARLY_PAGE_STACK_SIZE = 1024*1024; EFI_PHYSICAL_ADDRESS earlyPhypageStack = 0; if (EFI_ERROR(SystemTable->BootServices->AllocatePages(AllocateAnyPages, EfiLoaderData, EARLY_PAGE_STACK_SIZE / EFI_PAGE_SIZE, &earlyPhypageStack))) { puts(u"Could not allocate page stack\r\n"); return EFI_OUT_OF_RESOURCES; } SystemTable->BootServices->SetWatchdogTimer(0, 0, 0, nullptr); PrepareExitBootServices(); EfiMemoryMap map; map.MemMapSize = map.MapKey = map.DescriptorSize = map.DescriptorVersion = 0; SystemTable->BootServices->GetMemoryMap(&map.MemMapSize, nullptr, &map.MapKey, &map.DescriptorSize, &map.DescriptorVersion); //Give a nice bit of room to spare (memory map can change) map.MemMapSize += 16 * map.DescriptorSize; map.memmap = (EFI_MEMORY_DESCRIPTOR*)kmalloc(map.MemMapSize); //Allocate a nice buffer SystemTable->BootServices->GetMemoryMap(&map.MemMapSize, map.memmap, &map.MapKey, &map.DescriptorSize, &map.DescriptorVersion); printf(u"EFI Memory Map: Descriptor size %d\n", map.DescriptorSize); #if 0 //Dump the UEFI memory map to a file for testing EFI_FILE* file = OpenFile(u"efimap.dat", "w"); if (!file) { printf(u"Error: could not open %s: %s\r\n", u"efimap.dat", getError(getErrno())); } WriteFile(map.memmap, 1, map.MemMapSize, file); CloseFile(file); #endif if (EFI_ERROR(Status = SystemTable->BootServices->ExitBootServices(ImageHandle, map.MapKey))) { printf(u"Failed to exit boot services: %s\r\n", getError(Status)); UINTN index; SystemTable->BootServices->WaitForEvent(1, &SystemTable->ConIn->WaitForKey, &index); return EFI_SUCCESS; } //We need to take control of the hardware now. Setup basic memory management setLiballocAllocator(nullptr, nullptr); InitializePmmngr(map, (void*)earlyPhypageStack, EARLY_PAGE_STACK_SIZE); puts(u"Physical memory manager intialized\n"); arch_initialize_paging(); puts(u"Paging initialized\n"); setLiballocAllocator(&arch_allocate_pages, &arch_free_pages); //Now load the OS! bootfile = nullptr; kimage_entry kentry = nullptr; KLOAD_HANDLE kernel = NULL; while (bootfile = iterateBootFiles(bootfile)) { printf(u"Boot file: %s @ %x, length %d, type %d\n", bootfile->fileName, bootfile->loadLocation, bootfile->fileSize, bootfile->bootType); if (!bootfile->loadLocation) continue; if (bootfile->bootType == CHAIOS_DLL) { KLOAD_HANDLE dll = LoadImage(bootfile->loadLocation, bootfile->fileName); if (GetProcAddress(dll, "memcpy")) { set_memcpy((memcpy_proc)GetProcAddress(dll, "memcpy")); } } else if (bootfile->bootType == CHAIOS_KERNEL) { kernel = LoadImage(bootfile->loadLocation, bootfile->fileName); kentry = GetEntryPoint(kernel); } } size_t kstacksize = GetStackSize(kernel); if (!paging_map(stackaddr, PADDR_T_MAX, kstacksize, PAGE_ATTRIBUTE_WRITABLE)) { puts(u"Error: could not allocate kernel stack\n"); while (1); } KERNEL_BOOT_INFO bootinfo; fill_pmmngr_info(bootinfo.pmmngr_info); fill_arch_paging_info(bootinfo.paging_info); fill_modloader_info(bootinfo.modloader_info); get_framebuffer_info(bootinfo.fbinfo); populate_kterm_info(bootinfo.kterm_status); bootinfo.efi_system_table = SystemTable; bootinfo.memory_map = ↦ bootinfo.loaded_files = &bootfiles; bootinfo.boottype = CHAIOS_BOOT_TYPE_UEFI; bootinfo.printf_proc = &printf; bootinfo.puts_proc = &puts; printf(u"Success: Kernel entry point at %x, stack at %x, length %x\n", kentry, stackaddr, kstacksize); call_kernel(&bootinfo, kentry, stackaddr, kstacksize); puts(u"Kernel returned"); while (1); }
void gui_main(int argc, char **argv) { extern unsigned long BootPageDirectory; paging_map(&BootPageDirectory, (void *)0xC0400000, (void *)0x400000, 1024*1024*8, 0x7); lx = x = GUI_WIDTH/2; ly = y = GUI_HEIGHT/2; x = y = 50; task_create(gui_daemon, 0, "moused", 0); unsigned long frames = 0; unsigned long tickstart = kinfo.ticks; while (1) { if (running == 0) { if (kinfo.gui == 1) { vga_set_mode(vgadev, GUI_WIDTH, GUI_HEIGHT, GUI_BPP); running = 1; tickstart = kinfo.ticks; frames = 0; } continue; } else if (kinfo.gui == 0) { vga_unset_mode(vgadev); running = 0; tty_scrolldown(); continue; } frames++; // Clear vga_clear(vgadev, COLORBG); // Destop text vga_draw_string(vgadev, 0, 0, COLOR4, "EOS (Built %s %s)\n", __DATE__, __TIME__); vga_draw_string(vgadev, 0, 8, COLOR4, "Processor: %s", kinfo.cpuname); vga_draw_string(vgadev, 0, 16, COLOR4, "Memory: %dMB", kinfo.memory / 1024); vga_draw_string(vgadev, 0, 24, COLOR4, "Memory Used: %d", mm_used()); vga_draw_string(vgadev, 0, 40, COLOR4, "mSPF %d", (kinfo.ticks-tickstart)/frames); if (kinfo.ticks - tickstart > 100) vga_draw_string(vgadev, 0, 48, COLOR4, "FPS %d", frames / ((kinfo.ticks-tickstart)/100)); // Desktop icons //gui_draw_icon(vgadev, 8, 8); int winxnow, winynow; winxnow = winx; winynow = winy; gui_draw_window(vgadev, winxnow, winynow, 320, 240); gui_draw_icon(vgadev, winxnow+24, winynow+64); vga_draw_string(vgadev, winxnow+64, winynow+68, COLOR4, "Devices"); gui_draw_icon(vgadev, winxnow+24, winynow+96); vga_draw_string(vgadev, winxnow+64, winynow+100, COLOR4, "Users"); gui_draw_widget(vgadev, x, y); vga_flip(vgadev); } }