forked from BSB-WS23/mpstubs
166 lines
5.0 KiB
C++
166 lines
5.0 KiB
C++
|
#include "boot/multiboot/data.h"
|
||
|
|
||
|
/*! \brief Multiboot Information Structure according to Specification
|
||
|
* \see [Multiboot Specification]{#multiboot}
|
||
|
*/
|
||
|
struct multiboot_info {
|
||
|
/*! \brief Helper Structure
|
||
|
*/
|
||
|
struct Array {
|
||
|
uint32_t size; ///< Length
|
||
|
uint32_t addr; ///< Begin (physical address)
|
||
|
} __attribute__((packed));
|
||
|
|
||
|
enum Flag : uint32_t {
|
||
|
Memory = 1U << 0, ///< is there basic lower/upper memory information?
|
||
|
BootDev = 1U << 1, ///< is there a boot device set?
|
||
|
CmdLine = 1U << 2, ///< is the command-line defined?
|
||
|
Modules = 1U << 3, ///< are there modules to do something with?
|
||
|
/* These next two are mutually exclusive */
|
||
|
SymbolTable = 1U << 4, ///< is there an a.out symbol table loaded?
|
||
|
SectionHeader = 1U << 5, ///< is there an ELF section header table?
|
||
|
|
||
|
MemoryMap = 1U << 6, ///< is there a full memory map?
|
||
|
DriveInfo = 1U << 7, ///< Is there drive info?
|
||
|
ConfigTable = 1U << 8, ///< Is there a config table?
|
||
|
BootLoaderName = 1U << 9, ///< Is there a boot loader name?
|
||
|
ApmTable = 1U << 10, ///< Is there a APM table?
|
||
|
|
||
|
// Is there video information?
|
||
|
VbeInfo = 1U << 11, ///< Vesa bios extension
|
||
|
FramebufferInfo = 1U << 12 ///< Framebuffer
|
||
|
} flags;
|
||
|
|
||
|
/*! \brief Available memory retrieved from BIOS
|
||
|
*/
|
||
|
struct {
|
||
|
uint32_t lower; ///< Amount of memory below 1 MiB in kilobytes
|
||
|
uint32_t upper; ///< Amount of memory above 1 MiB in kilobytes
|
||
|
} mem __attribute__((packed));
|
||
|
uint32_t boot_device; ///< "root" partition
|
||
|
uint32_t cmdline; ///< Kernel command line
|
||
|
Array mods; ///< List of boot modules
|
||
|
union {
|
||
|
/*! \brief Symbol table for kernel in a.out format
|
||
|
*/
|
||
|
struct {
|
||
|
uint32_t tabsize;
|
||
|
uint32_t strsize;
|
||
|
uint32_t addr;
|
||
|
uint32_t reserved;
|
||
|
} aout_symbol_table __attribute__((packed));
|
||
|
|
||
|
/*! \brief Section header table for kernel in ELF
|
||
|
*/
|
||
|
struct {
|
||
|
uint32_t num; ///< Number of entries
|
||
|
uint32_t size; ///< Size per entry
|
||
|
uint32_t addr; ///< Start of the header table
|
||
|
uint32_t shndx; ///< String table index
|
||
|
} elf_section_header_table __attribute__((packed));
|
||
|
};
|
||
|
|
||
|
struct Array mmap; ///< Memory Map
|
||
|
struct Array drives; ///< Drive Information
|
||
|
uint32_t config_table; ///< ROM configuration table
|
||
|
uint32_t boot_loader_name; ///< Boot Loader Name
|
||
|
uint32_t apm_table; ///< APM table
|
||
|
|
||
|
struct Multiboot::VBE vbe; ///< VBE Information
|
||
|
struct Multiboot::Framebuffer framebuffer; ///< Framebuffer information
|
||
|
|
||
|
/*! \brief Check if setting is available
|
||
|
* \param flag Flag to check
|
||
|
* \return `true` if available
|
||
|
*/
|
||
|
bool has(enum Flag flag) const {
|
||
|
return (flags & flag) != 0;
|
||
|
}
|
||
|
} __attribute__((packed));
|
||
|
assert_size(multiboot_info, 116);
|
||
|
|
||
|
/*! \brief The pointer to the multiboot structures will be assigned in the assembler startup code (boot/startup.asm)
|
||
|
*/
|
||
|
struct multiboot_info *multiboot_addr = 0;
|
||
|
|
||
|
namespace Multiboot {
|
||
|
Module * getModule(unsigned i) {
|
||
|
if (multiboot_addr != nullptr &&
|
||
|
multiboot_addr->has(multiboot_info::Flag::Modules) &&
|
||
|
i < multiboot_addr->mods.size) {
|
||
|
return i + reinterpret_cast<Module*>(static_cast<uintptr_t>(multiboot_addr->mods.addr));
|
||
|
} else {
|
||
|
return nullptr;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
unsigned getModuleCount() {
|
||
|
return multiboot_addr->mods.size;
|
||
|
}
|
||
|
|
||
|
void * Memory::getStartAddress() const {
|
||
|
if (sizeof(void*) == 4 && (addr >> 32) != 0) {
|
||
|
return reinterpret_cast<void*>(addr & 0xffffffff);
|
||
|
} else {
|
||
|
return reinterpret_cast<void*>(static_cast<uintptr_t>(addr));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void * Memory::getEndAddress() const {
|
||
|
uint64_t end = addr + len;
|
||
|
if (sizeof(void*) == 4 && (end >> 32) != 0) {
|
||
|
return reinterpret_cast<void*>(end & 0xffffffff);
|
||
|
} else {
|
||
|
return reinterpret_cast<void*>(static_cast<uintptr_t>(end));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool Memory::isAvailable() const {
|
||
|
return type == AVAILABLE;
|
||
|
}
|
||
|
|
||
|
Memory * Memory::getNext() const {
|
||
|
if (multiboot_addr != nullptr && multiboot_addr->has(multiboot_info::Flag::MemoryMap)) {
|
||
|
uintptr_t next = reinterpret_cast<uintptr_t>(this) + size + sizeof(size);
|
||
|
if (next < multiboot_addr->mmap.addr + multiboot_addr->mmap.size) {
|
||
|
return reinterpret_cast<Memory *>(next);
|
||
|
}
|
||
|
}
|
||
|
return nullptr;
|
||
|
}
|
||
|
|
||
|
Memory * getMemoryMap() {
|
||
|
if (multiboot_addr != nullptr &&
|
||
|
multiboot_addr->has(multiboot_info::Flag::MemoryMap) &&
|
||
|
multiboot_addr->mmap.size > 0) {
|
||
|
return reinterpret_cast<Memory *>(static_cast<uintptr_t>(multiboot_addr->mmap.addr));
|
||
|
} else {
|
||
|
return nullptr;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
char * getCommandLine() {
|
||
|
return reinterpret_cast<char*>(static_cast<uintptr_t>(multiboot_addr->cmdline));
|
||
|
}
|
||
|
|
||
|
char * getBootLoader() {
|
||
|
return reinterpret_cast<char*>(static_cast<uintptr_t>(multiboot_addr->boot_loader_name));
|
||
|
}
|
||
|
|
||
|
VBE * getVesaBiosExtensionInfo() {
|
||
|
if (multiboot_addr != nullptr && multiboot_addr->has(multiboot_info::Flag::VbeInfo)) {
|
||
|
return &(multiboot_addr->vbe);
|
||
|
} else {
|
||
|
return nullptr;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Framebuffer * getFramebufferInfo() {
|
||
|
if (multiboot_addr != nullptr && multiboot_addr->has(multiboot_info::Flag::FramebufferInfo)) {
|
||
|
return &(multiboot_addr->framebuffer);
|
||
|
} else {
|
||
|
return nullptr;
|
||
|
}
|
||
|
}
|
||
|
} // namespace Multiboot
|