diff --git a/src/Main.cc b/src/Main.cc index 689282d..2c574c3 100644 --- a/src/Main.cc +++ b/src/Main.cc @@ -1,8 +1,17 @@ +/* Main.cc + * vim: set tw=80: + * Eryn Wells + */ +/** + * Entry point for the kernel in C/C++. + */ + #include #include #include "Console.hh" #include "Descriptors.hh" #include "Interrupts.hh" +#include "Multiboot.hh" #if defined(__linux__) #error "This file should be compiled with a cross-compiler, not the Linux system compiler!" @@ -19,10 +28,7 @@ kearly() { using kernel::Console; - /* - * Create a console object for early use because global initialization - * hasn't happened yet. - */ + // Create a console object for early use because global initialization hasn't happened yet. Console console; console.clear(kernel::Console::Color::Blue); console.printString("Loading system ...\n"); @@ -32,12 +38,19 @@ kearly() /** The beginning of the world... */ extern "C" void -kmain() +kmain(multiboot::Information *information) { + multiboot::Information::setInformation(information); + auto info = multiboot::Information::information(); + // Reinitialize the system console now that we have global static objects. auto& console = kernel::Console::systemConsole(); console.clear(kernel::Console::Color::Blue); + console.printString("Loading Polka ...\n"); + + console.printFormat("Detected memory: lower = %ld KB, upper = %ld KB\n", info->lowerMemoryKB(), info->upperMemoryKB()); + auto& gdt = x86::GDT::systemGDT(); gdt.setNullDescriptor(0); gdt.setDescriptor(1, x86::GDT::DescriptorSpec::kernelSegment(0, 0xFFFFFFFF, x86::GDT::Type::CodeEXR)); diff --git a/src/Multiboot.cc b/src/Multiboot.cc new file mode 100644 index 0000000..f8cc266 --- /dev/null +++ b/src/Multiboot.cc @@ -0,0 +1,87 @@ +/* Multiboot.cc + * vim: set tw=80: + * Eryn Wells + */ +/** + * Definition of multiboot stuff. + */ + +#include "Multiboot.hh" + +namespace { + +enum Present { + Memory = 1 << 0, + BootDevice = 1 << 1, + CommandLine = 1 << 2, + Modules = 1 << 3, + AOutSymbols = 1 << 4, + ElfSymbols = 1 << 5, + MemoryMap = 1 << 6, + Drives = 1 << 7, + ConfigurationTable = 1 << 8, + BootLoaderName = 1 << 9, + APMTable = 1 << 10, + VBE = 1 << 11, +}; + +multiboot::Information *sInformation = 0; + +} + +namespace multiboot { + +/* + * Static + */ + +const Information * +Information::information() +{ + return sInformation; +} + + +void +Information::setInformation(Information *info) +{ + sInformation = info; +} + +/* + * Public + */ + +uint32_t +Information::lowerMemoryKB() + const +{ + if ((mFlags & Present::Memory) == 0) { + return 0; + } + return mMemLower; +} + + +uint32_t +Information::upperMemoryKB() + const +{ + if ((mFlags & Present::Memory) == 0) { + return 0; + } + return mMemUpper; +} + + +const char * +Information::commandLine() + const +{ + if ((mFlags & Present::CommandLine) == 0) { + return 0; + } + return reinterpret_cast(mCommandLine); +} + +} /* namespace multiboot */ diff --git a/src/Multiboot.hh b/src/Multiboot.hh new file mode 100644 index 0000000..72b42d5 --- /dev/null +++ b/src/Multiboot.hh @@ -0,0 +1,167 @@ +/* Multiboot.hh + * vim: set tw=80: + * Eryn Wells + */ +/** + * Definition of the Multiboot structure. When grub boots, it fills in this + * structure and leaves a pointer to it in the EBX register. + */ + +#ifndef __MULTIBOOT_HH__ +#define __MULTIBOOT_HH__ + +#include "stdint.h" +#include "Attributes.hh" + +namespace multiboot { + +/** + * The multiboot information struct. Defined by the multiboot spec. + * See http://www.gnu.org/software/grub/manual/multiboot/multiboot.html#Machine-state + */ +struct PACKED Information +{ + static const Information *information(); + static void setInformation(Information* info); + + uint32_t lowerMemoryKB() const; + uint32_t upperMemoryKB() const; + const char* commandLine() const; + +private: + /** + * Bit field of flags. Fields below are only defined if the appropriate + * flag is set. + */ + uint32_t mFlags; + + /** Amount of lower (0 to 1 MB) memory, in KB. */ + uint32_t mMemLower; + /** Amount of upper (1 MB to ...) memory, in KB. Maximally, this value is the address of the first upper memory hole, minus 1 MB. */ + uint32_t mMemUpper; + + /** + * Indicates which BIOS disk the boot loader loaded the OS image from. + * Defined only if `bootDevice == true`. + */ + struct PACKED + { + /** Third level partition number. If unused this is set to 0xFF. */ + uint8_t partitionLevel3; + /** Sub-partition number. If unused this is set to 0xFF. */ + uint8_t partitionLevel2; + /** Top-level partition number. */ + uint8_t partitionLevel1; + /** + * BIOS drive number, as returned by the `INT 0x13` low-level disk + * interface. + */ + uint8_t driveNumber; + } bootDevice; + + /** + * Pointer to a C-style string containing the command line arguments. + * Defined only if `commandLinePresent == true`. + */ + uint32_t mCommandLine; + + /** + * Indicates what boot modules were loaded along with the kernel image. + * Defined only if `modulesPresent == true`. + */ + struct PACKED + { + /** Number of boot modules present. */ + uint32_t count; + /** Pointer to start of boot modules array. */ + uint32_t address; + } modules; + + // TODO: Document these. + union PACKED + { + struct PACKED + { + uint32_t tableSize; + uint32_t stringSize; + uint32_t address; + uint32_t reserved; + } aout; + + struct PACKED + { + uint32_t number; + uint32_t size; + uint32_t address; + uint32_t shndx; + } elf; + } symbols; + + /** + * Points to a buffer containing a memory map of the machine provided by the + * BIOS. Defined only if `memoryMapPresent == true`. + */ + struct PACKED + { + /** Number of memory map entries present. */ + uint32_t count; + /** Pointer to start of memory map entry array. */ + uint32_t address; + } memoryMap; + + /** + * Points to a buffer containing a list of drive definitions provided by the + * BIOS. Defined only if `drivesPresent == true`. + */ + struct PACKED + { + /** Number of memory map entries present. */ + uint32_t count; + /** Pointer to start of memory map entry array. */ + uint32_t address; + } drives; + + /** + * Pointer to the table containing APM information. Defined only if + * `apmTablePresent == true`. + */ + uint32_t apmTable; + + /** + * I dunno some VBE stuff. TODO. + */ + struct PACKED { + uint32_t controlInformation; + uint32_t modeInformation; + uint32_t mode; + uint32_t interfaceSegment; + uint32_t interfaceOff; + uint32_t interfaceLength; + } vbe; +}; + +struct PACKED Module +{ + /** Start address of boot module. */ + uint32_t start; + /** End address of boot module. */ + uint32_t end; + /** Pointer to a C-style boot module string. */ + uint32_t string; + /** Reserved and ignored. */ + uint32_t reserved; +}; + +// TODO: Define the MemoryMap struct +struct PACKED MemoryChunk +{ +}; + +// TODO: Define the Drive struct +struct PACKED Drive +{ +}; + +} /* namespace multiboot */ + +#endif /* __MULTIBOOT_HH__ */ diff --git a/src/boot.s b/src/boot.s index 78f0518..95714b4 100644 --- a/src/boot.s +++ b/src/boot.s @@ -41,7 +41,8 @@ _start: # Global initialization done here. call _init - # Here we go... + # Here we go... Give kmain the address of the multiboot info structure. + pushl %ebx call kmain # In case the function returns, we'll want to put the computer into an