#include "object/memory_object.h" #include "boot/boot_info.h" #include "debug/debug.h" #include "memory/physical_memory.h" #define K_MEM_DEBUG 0 MemoryObject::MemoryObject(uint64_t size) : size_(size) { if ((size & 0xFFF) != 0) { size_ = (size & ~0xFFF) + 0x1000; #if K_MEM_DEBUG dbgln("MemoryObject: aligned %x to %x", size, size_); #endif } // FIXME: Do this lazily. uint64_t num_pages = size_ / 0x1000; for (uint64_t i = 0; i < num_pages; i++) { phys_page_list_.PushBack(0); } } uint64_t MemoryObject::PhysicalPageAtOffset(uint64_t offset) { if (offset > size_) { panic("Invalid offset"); } uint64_t page_num = offset / 0x1000; return PageNumberToPhysAddr(page_num); } void MemoryObject::CopyBytesToObject(uint64_t source, uint64_t length) { if (length > size_) { panic("Copy overruns memory object: %x too large for %x", length, size_); } uint64_t hhdm = boot::GetHigherHalfDirectMap(); uint64_t page_number = 0; while (length > 0) { uint64_t physical = hhdm + PageNumberToPhysAddr(page_number); uint64_t bytes_to_copy = length >= 0x1000 ? 0x1000 : length; uint8_t* srcptr = reinterpret_cast(source); uint8_t* destptr = reinterpret_cast(physical); for (uint64_t i = 0; i < bytes_to_copy; i++) { destptr[i] = srcptr[i]; } length -= bytes_to_copy; source += 0x1000; page_number++; } } uint64_t MemoryObject::PageNumberToPhysAddr(uint64_t page_num) { auto iter = phys_page_list_.begin(); uint64_t index = 0; while (index < page_num) { ++iter; index++; } if (*iter == 0) { #if K_MEM_DEBUG dbgln("Allocating page num %u for mem object", page_num); #endif *iter = phys_mem::AllocatePage(); } return *iter; }