123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442 |
- /*++
- Copyright (c) 2013 Minoca Corp. All Rights Reserved
- Module Name:
- prochw.c
- Abstract:
- This module processor architecture specific support for the boot loader.
- Author:
- Evan Green 1-Aug-2013
- Environment:
- Boot
- --*/
- //
- // ------------------------------------------------------------------- Includes
- //
- #include <minoca/kernel/kernel.h>
- #include <minoca/kernel/bootload.h>
- #include <minoca/kernel/x86.h>
- //
- // ---------------------------------------------------------------- Definitions
- //
- #define BOOT_GDT_ENTRIES 3
- #define BOOT_IDT_SIZE (VECTOR_PROTECTION_FAULT + 1)
- //
- // ------------------------------------------------------ Data Type Definitions
- //
- //
- // ----------------------------------------------- Internal Function Prototypes
- //
- //
- // Assembly routines
- //
- VOID
- BoBreakExceptionHandlerAsm (
- ULONG ReturnEip,
- ULONG ReturnCodeSelector,
- ULONG ReturnEflags
- );
- VOID
- BoSingleStepExceptionHandlerAsm (
- ULONG ReturnEip,
- ULONG ReturnCodeSelector,
- ULONG ReturnEflags
- );
- VOID
- BoDebugServiceHandlerAsm (
- ULONG ReturnEip,
- ULONG ReturnCodeSelector,
- ULONG ReturnEflags
- );
- VOID
- BoProtectionFaultHandlerAsm (
- ULONG ReturnEip,
- ULONG ReturnCodeSelector,
- ULONG ReturnEflags
- );
- VOID
- BoLoadBootDataSegments (
- VOID
- );
- //
- // C routines
- //
- VOID
- BopInitializeGdt (
- PGDT_ENTRY GdtTable
- );
- VOID
- BopInitializeInterrupts (
- PVOID Idt
- );
- VOID
- BopCreateGate (
- PPROCESSOR_GATE Gate,
- PVOID HandlerRoutine,
- USHORT Selector,
- UCHAR Type,
- UCHAR Privilege
- );
- VOID
- BopCreateSegmentDescriptor (
- PGDT_ENTRY GdtEntry,
- PVOID Base,
- ULONG Limit,
- GDT_GRANULARITY Granularity,
- GDT_SEGMENT_TYPE Access,
- UCHAR PrivilegeLevel,
- BOOL System
- );
- //
- // -------------------------------------------------------------------- Globals
- //
- //
- // Store global processor structures.
- //
- GDT_ENTRY BoGdt[BOOT_GDT_ENTRIES];
- PROCESSOR_GATE BoIdt[BOOT_IDT_SIZE];
- //
- // ------------------------------------------------------------------ Functions
- //
- VOID
- BoInitializeProcessor (
- VOID
- )
- /*++
- Routine Description:
- This routine initializes processor-specific structures. In the case of x86,
- it initializes the GDT and TSS.
- Arguments:
- None.
- Return Value:
- None.
- --*/
- {
- //
- // Initialize and load the GDT and Tasks.
- //
- BopInitializeGdt(BoGdt);
- BopInitializeInterrupts(BoIdt);
- return;
- }
- //
- // --------------------------------------------------------- Internal Functions
- //
- VOID
- BopInitializeGdt (
- PGDT_ENTRY GdtTable
- )
- /*++
- Routine Description:
- This routine initializes and loads the system's Global Descriptor Table
- (GDT).
- Arguments:
- GdtTable - Supplies a pointer to the global descriptor table to use. It is
- assumed this table contains enough entries to hold all the segment
- descriptors.
- Return Value:
- None.
- --*/
- {
- TABLE_REGISTER Gdt;
- //
- // The first segment descriptor must be unused. Set it to zero.
- //
- GdtTable[0].LimitLow = 0;
- GdtTable[0].BaseLow = 0;
- GdtTable[0].BaseMiddle = 0;
- GdtTable[0].Access = 0;
- GdtTable[0].Granularity = 0;
- GdtTable[0].BaseHigh = 0;
- //
- // Initialize the kernel code segment. Initialize the entry to cover all
- // 4GB of memory, with read/write permissions, and only on ring 0. This is
- // not a system segment.
- //
- BopCreateSegmentDescriptor(&(GdtTable[KERNEL_CS / sizeof(GDT_ENTRY)]),
- NULL,
- MAX_GDT_LIMIT,
- GdtKilobyteGranularity,
- GdtCodeExecuteOnly,
- 0,
- FALSE);
- //
- // Initialize the kernel data segment. Initialize the entry to cover
- // all 4GB of memory, with read/write permissions, and only on ring 0. This
- // is not a system segment.
- //
- BopCreateSegmentDescriptor(&(GdtTable[KERNEL_DS / sizeof(GDT_ENTRY)]),
- NULL,
- MAX_GDT_LIMIT,
- GdtKilobyteGranularity,
- GdtDataReadWrite,
- 0,
- FALSE);
- //
- // Install the new GDT table.
- //
- Gdt.Limit = sizeof(GDT_ENTRY) * BOOT_GDT_ENTRIES;
- Gdt.Base = (ULONG)GdtTable;
- ArLoadGdtr(Gdt);
- BoLoadBootDataSegments();
- return;
- }
- VOID
- BopInitializeInterrupts (
- PVOID Idt
- )
- /*++
- Routine Description:
- This routine initializes and enables interrupts.
- Arguments:
- Idt - Supplies a pointer to the Interrrupt Descriptor Table for this
- processor.
- Return Value:
- None.
- --*/
- {
- TABLE_REGISTER IdtRegister;
- PPROCESSOR_GATE IdtTable;
- IdtTable = Idt;
- //
- // Set up the debug trap handlers.
- //
- BopCreateGate(IdtTable + VECTOR_BREAKPOINT,
- BoBreakExceptionHandlerAsm,
- KERNEL_CS,
- INTERRUPT_GATE_TYPE,
- 3);
- BopCreateGate(IdtTable + VECTOR_DEBUG,
- BoSingleStepExceptionHandlerAsm,
- KERNEL_CS,
- INTERRUPT_GATE_TYPE,
- 0);
- BopCreateGate(IdtTable + VECTOR_PROTECTION_FAULT,
- BoProtectionFaultHandlerAsm,
- KERNEL_CS,
- INTERRUPT_GATE_TYPE,
- 0);
- //
- // Load the IDT register with our interrupt descriptor table.
- //
- IdtRegister.Limit = (BOOT_IDT_SIZE * 8) - 1;
- IdtRegister.Base = (ULONG)IdtTable;
- ArLoadIdtr(&IdtRegister);
- return;
- }
- VOID
- BopCreateGate (
- PPROCESSOR_GATE Gate,
- PVOID HandlerRoutine,
- USHORT Selector,
- UCHAR Type,
- UCHAR Privilege
- )
- /*++
- Routine Description:
- This routine initializes a task, call, trap, or interrupt gate with the
- given values.
- Arguments:
- Gate - Supplies a pointer to the structure where the gate will be returned.
- It is assumed this structure is already allocated.
- HandlerRoutine - Supplies a pointer to the destination routine of this gate.
- Selector - Supplies the code selector this gate should run in.
- Type - Supplies the type of the gate. Set this to CALL_GATE_TYPE,
- INTERRUPT_GATE_TYPE, TASK_GATE_TYPE, or TRAP_GATE_TYPE.
- Privilege - Supplies the privilege level this gate should run in. 0 is the
- most privileged level, and 3 is the least privileged.
- Return Value:
- None.
- --*/
- {
- Gate->LowOffset = (USHORT)((ULONG)HandlerRoutine & 0xFFFF);
- Gate->HighOffset = (USHORT)((ULONG)HandlerRoutine >> 16);
- Gate->Selector = Selector;
- //
- // Set bit 5-7 of the count to 0. Bits 4-0 are reserved and need to be set
- // to 0 as well.
- //
- Gate->Count = 0;
- //
- // Access is programmed as follows:
- // Bit 7: Present. Set to 1 to indicate that this gate is present.
- // Bits 5-6: Privilege level.
- // Bit 4: Set to 0 to indicate it's a system gate.
- // Bits 3-0: Type.
- //
- Gate->Access = Type | (Privilege << 5) | (1 << 7);
- return;
- }
- VOID
- BopCreateSegmentDescriptor (
- PGDT_ENTRY GdtEntry,
- PVOID Base,
- ULONG Limit,
- GDT_GRANULARITY Granularity,
- GDT_SEGMENT_TYPE Access,
- UCHAR PrivilegeLevel,
- BOOL System
- )
- /*++
- Routine Description:
- This routine initializes a GDT entry given the parameters.
- Arguments:
- GdtEntry - Supplies a pointer to the GDT entry that will be initialized.
- Base - Supplies the base address where this segment begins.
- Limit - Supplies the size of the segment, either in bytes or kilobytes,
- depending on the Granularity parameter.
- Granularity - Supplies the granularity of the segment. Valid values are byte
- granularity or kilobyte granularity.
- Access - Supplies the access permissions on the segment.
- PrivilegeLevel - Supplies the privilege level that this segment requires.
- Valid values are 0 (most privileged, kernel) to 3 (user mode, least
- privileged).
- System - Supplies a flag indicating whether this is a system segment (TRUE)
- or a code/data segment.
- Return Value:
- None.
- --*/
- {
- //
- // If all these magic numbers seem cryptic, see the comment above the
- // definition for the GDT_ENTRY structure.
- //
- GdtEntry->LimitLow = Limit & 0xFFFF;
- GdtEntry->BaseLow = (ULONG)Base & 0xFFFF;
- GdtEntry->BaseMiddle = ((ULONG)Base >> 16) & 0xFF;
- GdtEntry->Access = DEFAULT_GDT_ACCESS |
- ((PrivilegeLevel & 0x3) << 5) |
- (Access & 0xF);
- if (System != FALSE) {
- GdtEntry->Access |= GDT_SYSTEM_SEGMENT;
- } else {
- GdtEntry->Access |= GDT_CODE_DATA_SEGMENT;
- }
- GdtEntry->Granularity = DEFAULT_GDT_GRANULARITY |
- Granularity |
- ((Limit >> 16) & 0xF);
- GdtEntry->BaseHigh = ((ULONG)Base >> 24) & 0xFF;
- return;
- }
|