Setup processor context (GDT, PCR, TSS) and kernel startup stack before booting XTOS
All checks were successful
ci/woodpecker/push/build Pipeline was successful
All checks were successful
ci/woodpecker/push/build Pipeline was successful
This commit is contained in:
parent
3ad3149f80
commit
3b08bcaa4f
@ -10,7 +10,8 @@ include_directories(
|
|||||||
# Specify list of source code files
|
# Specify list of source code files
|
||||||
list(APPEND XTLDR_XTOS_SOURCE
|
list(APPEND XTLDR_XTOS_SOURCE
|
||||||
${XTLDR_SOURCE_DIR}/blproto.c
|
${XTLDR_SOURCE_DIR}/blproto.c
|
||||||
${XTLDR_XTOS_SOURCE_DIR}/xtos.c)
|
${XTLDR_XTOS_SOURCE_DIR}/xtos.c
|
||||||
|
${XTLDR_XTOS_SOURCE_DIR}/${ARCH}/cpu.c)
|
||||||
|
|
||||||
# Link bootloader executable
|
# Link bootloader executable
|
||||||
add_executable(xtos ${XTLDR_XTOS_SOURCE})
|
add_executable(xtos ${XTLDR_XTOS_SOURCE})
|
||||||
|
251
xtldr/modules/xtos/amd64/cpu.c
Normal file
251
xtldr/modules/xtos/amd64/cpu.c
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
/**
|
||||||
|
* PROJECT: ExectOS
|
||||||
|
* COPYRIGHT: See COPYING.md in the top level directory
|
||||||
|
* FILE: xtldr/modules/xtos/amd64/cpu.c
|
||||||
|
* DESCRIPTION: XTOS AMD64 processor context
|
||||||
|
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <xtos.h>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fills in an AMD64 GDT entry.
|
||||||
|
*
|
||||||
|
* @param Gdt
|
||||||
|
* Supplies a pointer to the GDT.
|
||||||
|
*
|
||||||
|
* @param Selector
|
||||||
|
* Specifies a segment selector of the GDT entry.
|
||||||
|
*
|
||||||
|
* @param Base
|
||||||
|
* Specifies a base address value of the descriptor.
|
||||||
|
*
|
||||||
|
* @param Limit
|
||||||
|
* Specifies a descriptor limit.
|
||||||
|
*
|
||||||
|
* @param Type
|
||||||
|
* Specifies a type of the descriptor.
|
||||||
|
*
|
||||||
|
* @param Dpl
|
||||||
|
* Specifies the descriptor privilege level.
|
||||||
|
*
|
||||||
|
* @param SegmentMode
|
||||||
|
* Specifies a segment mode of the descriptor.
|
||||||
|
*
|
||||||
|
* @return This routine does not return any value
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTCDECL
|
||||||
|
VOID
|
||||||
|
XtpInitializeGdtEntry(IN PKGDTENTRY Gdt,
|
||||||
|
IN USHORT Selector,
|
||||||
|
IN ULONGLONG Base,
|
||||||
|
IN ULONG Limit,
|
||||||
|
IN UCHAR Type,
|
||||||
|
IN UCHAR Dpl,
|
||||||
|
IN UCHAR SegmentMode)
|
||||||
|
{
|
||||||
|
PKGDTENTRY GdtEntry;
|
||||||
|
UCHAR Granularity;
|
||||||
|
|
||||||
|
/* Set the granularity flag depending on descriptor limit */
|
||||||
|
if(Limit < 0x100000)
|
||||||
|
{
|
||||||
|
/* Limit is in 1B blocks */
|
||||||
|
Granularity = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Limit is in 4KB blocks */
|
||||||
|
Granularity = 1;
|
||||||
|
Limit >>= 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get GDT entry */
|
||||||
|
GdtEntry = (PKGDTENTRY)((ULONG64)Gdt + (Selector & ~RPL_MASK));
|
||||||
|
|
||||||
|
/* Set GDT descriptor base */
|
||||||
|
GdtEntry->BaseLow = Base & 0xFFFF;
|
||||||
|
GdtEntry->Bits.BaseMiddle = (Base >> 16) & 0xFF;
|
||||||
|
GdtEntry->Bits.BaseHigh = (Base >> 24) & 0xFF;
|
||||||
|
GdtEntry->BaseUpper = Base >> 32;
|
||||||
|
|
||||||
|
/* Set descriptor limit */
|
||||||
|
GdtEntry->LimitLow = Limit & 0xFFFF;
|
||||||
|
GdtEntry->Bits.LimitHigh = (Limit >> 16) & 0xF;
|
||||||
|
|
||||||
|
/* Initialize GDT entry */
|
||||||
|
GdtEntry->Bits.DefaultBig = (SegmentMode & 2);
|
||||||
|
GdtEntry->Bits.Dpl = (Dpl & 0x3);
|
||||||
|
GdtEntry->Bits.Granularity = Granularity;
|
||||||
|
GdtEntry->Bits.LongMode = (SegmentMode & 1);
|
||||||
|
GdtEntry->Bits.Present = (Type != 0);
|
||||||
|
GdtEntry->Bits.System = 0;
|
||||||
|
GdtEntry->Bits.Type = (Type & 0x1F);
|
||||||
|
GdtEntry->MustBeZero = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes GDT and TSS descriptors.
|
||||||
|
*
|
||||||
|
* @param MemoryMappings
|
||||||
|
* Supplies a pointer to linked list containing all memory mappings.
|
||||||
|
*
|
||||||
|
* @param VirtualAddress
|
||||||
|
* Supplies a pointer to the next valid, free and available virtual address.
|
||||||
|
*
|
||||||
|
* @param Gdt
|
||||||
|
* Supplies a pointer to memory area containing GDT to fill in.
|
||||||
|
*
|
||||||
|
* @return This routine returns a status code.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTCDECL
|
||||||
|
EFI_STATUS
|
||||||
|
XtpInitializeDescriptors(IN PLIST_ENTRY MemoryMappings,
|
||||||
|
IN PVOID *VirtualAddress,
|
||||||
|
OUT PKGDTENTRY *Gdt)
|
||||||
|
{
|
||||||
|
EFI_PHYSICAL_ADDRESS GdtAddress, TssAddress;
|
||||||
|
PKTSS PhysicalTss, Tss;
|
||||||
|
PKGDTENTRY GdtEntry;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
/* Print debug message */
|
||||||
|
XtLdrProtocol->DbgPrint(L"Initializing Task State Segment (TSS)\n");
|
||||||
|
|
||||||
|
/* Allocate memory for TSS */
|
||||||
|
Status = XtLdrProtocol->AllocatePages(EFI_SIZE_TO_PAGES(sizeof(KTSS)), &TssAddress);
|
||||||
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Memory allocation failure */
|
||||||
|
XtLdrProtocol->DbgPrint(L"Failed to allocate pages for TSS (Status Code: %lx)\n", Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set TSS and fill it with zeroes */
|
||||||
|
PhysicalTss = (PKTSS)(UINT_PTR)TssAddress;
|
||||||
|
RtlZeroMemory(PhysicalTss, EFI_SIZE_TO_PAGES(sizeof(KTSS)) * EFI_PAGE_SIZE);
|
||||||
|
|
||||||
|
/* Set RSP0 to point at the end of kernel startup stack */
|
||||||
|
PhysicalTss->Rsp0 = (UINT_PTR)*VirtualAddress;
|
||||||
|
|
||||||
|
/* Map TSS and set its virtual address */
|
||||||
|
XtLdrProtocol->AddVirtualMemoryMapping(MemoryMappings, *VirtualAddress, PhysicalTss,
|
||||||
|
EFI_SIZE_TO_PAGES(sizeof(KTSS)), LoaderMemoryData);
|
||||||
|
Tss = (PKTSS)*VirtualAddress;
|
||||||
|
|
||||||
|
/* Set next valid virtual address */
|
||||||
|
*VirtualAddress += EFI_SIZE_TO_PAGES(sizeof(KTSS)) * EFI_PAGE_SIZE;
|
||||||
|
|
||||||
|
/* Print debug message */
|
||||||
|
XtLdrProtocol->DbgPrint(L"Initializing General Descriptor Table (GDT)\n");
|
||||||
|
|
||||||
|
/* Allocate memory for GDT */
|
||||||
|
Status = XtLdrProtocol->AllocatePages(EFI_SIZE_TO_PAGES(128 * sizeof(KGDTENTRY)), &GdtAddress);
|
||||||
|
if (Status != STATUS_EFI_SUCCESS) {
|
||||||
|
/* Memory allocation failure */
|
||||||
|
XtLdrProtocol->DbgPrint(L"Failed to allocate pages for GDT (Status Code: %lx)\n", Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set GDT entry and fill it with zeroes */
|
||||||
|
GdtEntry = (PKGDTENTRY)(UINT_PTR)GdtAddress;
|
||||||
|
RtlZeroMemory(GdtEntry, EFI_SIZE_TO_PAGES(128 * sizeof(KGDTENTRY)) * EFI_PAGE_SIZE);
|
||||||
|
|
||||||
|
/* Initialize GDT entries */
|
||||||
|
XtpInitializeGdtEntry(GdtEntry, KGDT_NULL, 0x0, 0x0, 0, KGDT_DPL_SYSTEM, 0);
|
||||||
|
XtpInitializeGdtEntry(GdtEntry, KGDT_R0_CODE, 0x0, 0x0, KGDT_TYPE_CODE, KGDT_DPL_SYSTEM, 0);
|
||||||
|
XtpInitializeGdtEntry(GdtEntry, KGDT_R0_DATA, 0x0, 0x0, KGDT_TYPE_DATA, KGDT_DPL_SYSTEM, 0);
|
||||||
|
XtpInitializeGdtEntry(GdtEntry, KGDT_R3_CODE, 0x0, 0x0, KGDT_TYPE_CODE, KGDT_DPL_USER, 0);
|
||||||
|
XtpInitializeGdtEntry(GdtEntry, KGDT_R3_DATA, 0x0, 0xFFFFFFFF, KGDT_TYPE_DATA, KGDT_DPL_USER, 2);
|
||||||
|
XtpInitializeGdtEntry(GdtEntry, KGDT_R3_CMCODE, 0x0, 0xFFFFFFFF, KGDT_TYPE_CODE, KGDT_DPL_USER, 2);
|
||||||
|
XtpInitializeGdtEntry(GdtEntry, KGDT_R3_CMTEB, 0x0, 0x0FFF, KGDT_TYPE_DATA, KGDT_DPL_USER, 2);
|
||||||
|
XtpInitializeGdtEntry(GdtEntry, KGDT_R0_LDT, 0, 0xFFFFFFFF, KGDT_TYPE_CODE, KGDT_DPL_SYSTEM, 0);
|
||||||
|
XtpInitializeGdtEntry(GdtEntry, KGDT_SYS_TSS, (ULONG_PTR)Tss, sizeof(KTSS), AMD64_TSS, KGDT_DPL_SYSTEM, 0);
|
||||||
|
|
||||||
|
/* Map GDT and set its virtual address */
|
||||||
|
Status = XtLdrProtocol->AddVirtualMemoryMapping(MemoryMappings, *VirtualAddress, GdtEntry,
|
||||||
|
EFI_SIZE_TO_PAGES(128 * sizeof(KGDTENTRY)), LoaderMemoryData);
|
||||||
|
*Gdt = (PKGDTENTRY)*VirtualAddress;
|
||||||
|
|
||||||
|
/* Set next valid virtual address */
|
||||||
|
*VirtualAddress += (EFI_SIZE_TO_PAGES(128 * sizeof(KGDTENTRY)) * EFI_PAGE_SIZE);
|
||||||
|
|
||||||
|
/* Return success */
|
||||||
|
return STATUS_EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads previously prepared CPU context and performs architecture-specific tasks needed to boot XTOS.
|
||||||
|
*
|
||||||
|
* @param Gdt
|
||||||
|
* Supplies a pointer to memory area containing GDT to load.
|
||||||
|
*
|
||||||
|
* @return This routine does not return any value.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTCDECL
|
||||||
|
VOID
|
||||||
|
XtpLoadProcessorContext(IN PKGDTENTRY Gdt)
|
||||||
|
{
|
||||||
|
KDESCRIPTOR GdtDescriptor;
|
||||||
|
|
||||||
|
GdtDescriptor.Base = Gdt;
|
||||||
|
GdtDescriptor.Limit = 128 * sizeof(KGDTENTRY) - 1;
|
||||||
|
|
||||||
|
/* Load GDT and TSS */
|
||||||
|
HlLoadGlobalDescriptorTable(&GdtDescriptor.Limit);
|
||||||
|
HlLoadTaskRegister((UINT32)KGDT_SYS_TSS);
|
||||||
|
|
||||||
|
/* Re-enable IDE interrupts */
|
||||||
|
HlIoPortOutByte(0x376, 0);
|
||||||
|
HlIoPortOutByte(0x3F6, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets architecture specific processor context.
|
||||||
|
*
|
||||||
|
* @param MemoryMappings
|
||||||
|
* Supplies a pointer to linked list containing all memory mappings.
|
||||||
|
*
|
||||||
|
* @param VirtualAddress
|
||||||
|
* Supplies a pointer to the next valid, free and available virtual address.
|
||||||
|
*
|
||||||
|
* @param Gdt
|
||||||
|
* Supplies a pointer to memory area containing GDT to fill in.
|
||||||
|
*
|
||||||
|
* @return This routine returns a status code.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTCDECL
|
||||||
|
EFI_STATUS
|
||||||
|
XtpSetProcessorContext(IN PLIST_ENTRY MemoryMappings,
|
||||||
|
IN PVOID *VirtualAddress,
|
||||||
|
OUT PKGDTENTRY *Gdt)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
/* Print debug message */
|
||||||
|
XtLdrProtocol->DbgPrint(L"Setting processor context\n");
|
||||||
|
|
||||||
|
/* Disable interrupts */
|
||||||
|
HlClearInterruptFlag();
|
||||||
|
|
||||||
|
/* Initialize GDT */
|
||||||
|
Status = XtpInitializeDescriptors(MemoryMappings, VirtualAddress, Gdt);
|
||||||
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
|
{
|
||||||
|
/* GDT initialization failure */
|
||||||
|
XtLdrProtocol->DbgPrint(L"Failed to initialize GDT (Status Code: %lx)\n", Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return success */
|
||||||
|
return STATUS_EFI_SUCCESS;
|
||||||
|
}
|
278
xtldr/modules/xtos/i686/cpu.c
Normal file
278
xtldr/modules/xtos/i686/cpu.c
Normal file
@ -0,0 +1,278 @@
|
|||||||
|
/**
|
||||||
|
* PROJECT: ExectOS
|
||||||
|
* COPYRIGHT: See COPYING.md in the top level directory
|
||||||
|
* FILE: xtldr/modules/xtos/i686/cpu.c
|
||||||
|
* DESCRIPTION: XTOS i686 processor context
|
||||||
|
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <xtos.h>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fills in an AMD64 GDT entry.
|
||||||
|
*
|
||||||
|
* @param Gdt
|
||||||
|
* Supplies a pointer to the GDT.
|
||||||
|
*
|
||||||
|
* @param Selector
|
||||||
|
* Specifies a segment selector of the GDT entry.
|
||||||
|
*
|
||||||
|
* @param Base
|
||||||
|
* Specifies a base address value of the descriptor.
|
||||||
|
*
|
||||||
|
* @param Limit
|
||||||
|
* Specifies a descriptor limit.
|
||||||
|
*
|
||||||
|
* @param Type
|
||||||
|
* Specifies a type of the descriptor.
|
||||||
|
*
|
||||||
|
* @param Dpl
|
||||||
|
* Specifies the descriptor privilege level.
|
||||||
|
*
|
||||||
|
* @param SegmentMode
|
||||||
|
* Specifies a segment mode of the descriptor.
|
||||||
|
*
|
||||||
|
* @return This routine does not return any value
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTCDECL
|
||||||
|
VOID
|
||||||
|
XtpInitializeGdtEntry(IN PKGDTENTRY Gdt,
|
||||||
|
IN USHORT Selector,
|
||||||
|
IN ULONGLONG Base,
|
||||||
|
IN ULONG Limit,
|
||||||
|
IN UCHAR Type,
|
||||||
|
IN UCHAR Dpl,
|
||||||
|
IN UCHAR SegmentMode)
|
||||||
|
{
|
||||||
|
PKGDTENTRY GdtEntry;
|
||||||
|
UCHAR Granularity;
|
||||||
|
|
||||||
|
/* Set the granularity flag depending on descriptor limit */
|
||||||
|
if(Limit < 0x100000)
|
||||||
|
{
|
||||||
|
/* Limit is in 1B blocks */
|
||||||
|
Granularity = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Limit is in 4KB blocks */
|
||||||
|
Granularity = 1;
|
||||||
|
Limit >>= 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get GDT entry */
|
||||||
|
GdtEntry = (PKGDTENTRY)((ULONG64)Gdt + (Selector & ~RPL_MASK));
|
||||||
|
|
||||||
|
/* Set GDT descriptor base */
|
||||||
|
GdtEntry->BaseLow = Base & 0xFFFF;
|
||||||
|
GdtEntry->Bits.BaseMiddle = (Base >> 16) & 0xFF;
|
||||||
|
GdtEntry->Bits.BaseHigh = (Base >> 24) & 0xFF;
|
||||||
|
|
||||||
|
/* Set descriptor limit */
|
||||||
|
GdtEntry->LimitLow = Limit & 0xFFFF;
|
||||||
|
GdtEntry->Bits.LimitHigh = (Limit >> 16) & 0xF;
|
||||||
|
|
||||||
|
/* Initialize GDT entry */
|
||||||
|
GdtEntry->Bits.DefaultBig = (SegmentMode & 2);
|
||||||
|
GdtEntry->Bits.Dpl = (Dpl & 0x3);
|
||||||
|
GdtEntry->Bits.Granularity = Granularity;
|
||||||
|
GdtEntry->Bits.Reserved0 = 0;
|
||||||
|
GdtEntry->Bits.Present = (Type != 0);
|
||||||
|
GdtEntry->Bits.System = 0;
|
||||||
|
GdtEntry->Bits.Type = (Type & 0x1F);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PCR_PAGES 7
|
||||||
|
/**
|
||||||
|
* Initializes GDT, PCR and TSS descriptors.
|
||||||
|
*
|
||||||
|
* @param MemoryMappings
|
||||||
|
* Supplies a pointer to linked list containing all memory mappings.
|
||||||
|
*
|
||||||
|
* @param VirtualAddress
|
||||||
|
* Supplies a pointer to the next valid, free and available virtual address.
|
||||||
|
*
|
||||||
|
* @param Gdt
|
||||||
|
* Supplies a pointer to memory area containing GDT to fill in.
|
||||||
|
*
|
||||||
|
* @return This routine returns a status code.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTCDECL
|
||||||
|
EFI_STATUS
|
||||||
|
XtpInitializeDescriptors(IN PLIST_ENTRY MemoryMappings,
|
||||||
|
IN PVOID *VirtualAddress,
|
||||||
|
OUT PKGDTENTRY *Gdt)
|
||||||
|
{
|
||||||
|
EFI_PHYSICAL_ADDRESS GdtAddress, PcrAddress, TssAddress;
|
||||||
|
PKTSS PhysicalTss, Tss;
|
||||||
|
PVOID PhysicalPcr, Pcr;
|
||||||
|
PKGDTENTRY GdtEntry;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
/* Print debug message */
|
||||||
|
XtLdrProtocol->DbgPrint(L"Initializing Task State Segment (TSS)\n");
|
||||||
|
|
||||||
|
/* Allocate memory for TSS */
|
||||||
|
Status = XtLdrProtocol->AllocatePages(EFI_SIZE_TO_PAGES(sizeof(KTSS)), &TssAddress);
|
||||||
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Memory allocation failure */
|
||||||
|
XtLdrProtocol->DbgPrint(L"Failed to allocate pages for TSS (Status Code: %lx)\n", Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set TSS and fill it with zeroes */
|
||||||
|
PhysicalTss = (PKTSS)(UINT_PTR)TssAddress;
|
||||||
|
RtlZeroMemory(PhysicalTss, EFI_SIZE_TO_PAGES(sizeof(KTSS)) * EFI_PAGE_SIZE);
|
||||||
|
|
||||||
|
/* Map TSS and set its virtual address */
|
||||||
|
XtLdrProtocol->AddVirtualMemoryMapping(MemoryMappings, *VirtualAddress, PhysicalTss,
|
||||||
|
EFI_SIZE_TO_PAGES(sizeof(KTSS)), LoaderMemoryData);
|
||||||
|
Tss = (PKTSS)*VirtualAddress;
|
||||||
|
|
||||||
|
/* Set next valid virtual address */
|
||||||
|
*VirtualAddress += EFI_SIZE_TO_PAGES(sizeof(KTSS)) * EFI_PAGE_SIZE;
|
||||||
|
|
||||||
|
/* Print debug message */
|
||||||
|
XtLdrProtocol->DbgPrint(L"Initializing Processor Control Region (PCR)\n");
|
||||||
|
|
||||||
|
/* Allocate memory for PCR */
|
||||||
|
Status = XtLdrProtocol->AllocatePages(PCR_PAGES, &PcrAddress);
|
||||||
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Memory allocation failure */
|
||||||
|
XtLdrProtocol->DbgPrint(L"Failed to allocate pages for PCR (Status Code: %lx)\n", Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set PCR and fill it with zeroes */
|
||||||
|
PhysicalPcr = (PVOID)(UINT_PTR)PcrAddress;
|
||||||
|
RtlZeroMemory(PhysicalPcr, PCR_PAGES * EFI_PAGE_SIZE);
|
||||||
|
|
||||||
|
/* Map TSS and set its virtual address */
|
||||||
|
XtLdrProtocol->AddVirtualMemoryMapping(MemoryMappings, *VirtualAddress, PhysicalPcr,
|
||||||
|
PCR_PAGES, LoaderStartupPcrPage);
|
||||||
|
Pcr = *VirtualAddress;
|
||||||
|
|
||||||
|
/* Set next valid virtual address */
|
||||||
|
*VirtualAddress += PCR_PAGES * EFI_PAGE_SIZE;
|
||||||
|
|
||||||
|
/* Print debug message */
|
||||||
|
XtLdrProtocol->DbgPrint(L"Initializing General Descriptor Table (GDT)\n");
|
||||||
|
|
||||||
|
/* Allocate memory for GDT */
|
||||||
|
Status = XtLdrProtocol->AllocatePages(EFI_SIZE_TO_PAGES(128 * sizeof(KGDTENTRY)), &GdtAddress);
|
||||||
|
if (Status != STATUS_EFI_SUCCESS) {
|
||||||
|
/* Memory allocation failure */
|
||||||
|
XtLdrProtocol->DbgPrint(L"Failed to allocate pages for GDT (Status Code: %lx)\n", Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set GDT entry and fill it with zeroes */
|
||||||
|
GdtEntry = (PKGDTENTRY)(UINT_PTR)GdtAddress;
|
||||||
|
RtlZeroMemory(GdtEntry, EFI_SIZE_TO_PAGES(128 * sizeof(KGDTENTRY)) * EFI_PAGE_SIZE);
|
||||||
|
|
||||||
|
/* Initialize GDT entries */
|
||||||
|
XtpInitializeGdtEntry(GdtEntry, KGDT_NULL, 0x0, 0x0, 0, KGDT_DPL_SYSTEM, 0);
|
||||||
|
XtpInitializeGdtEntry(GdtEntry, KGDT_R0_CODE, 0x0, 0xFFFFFFFF, KGDT_TYPE_CODE, KGDT_DPL_SYSTEM, 2);
|
||||||
|
XtpInitializeGdtEntry(GdtEntry, KGDT_R0_DATA, 0x0, 0xFFFFFFFF, KGDT_TYPE_DATA, KGDT_DPL_SYSTEM, 2);
|
||||||
|
XtpInitializeGdtEntry(GdtEntry, KGDT_R3_CODE, 0x0, 0xFFFFFFFF, KGDT_TYPE_CODE, KGDT_DPL_USER, 2);
|
||||||
|
XtpInitializeGdtEntry(GdtEntry, KGDT_R3_DATA, 0x0, 0xFFFFFFFF, KGDT_TYPE_DATA, KGDT_DPL_USER, 2);
|
||||||
|
XtpInitializeGdtEntry(GdtEntry, KGDT_R3_TEB, 0x0, 0xFFF, KGDT_TYPE_DATA | KGDT_DESCRIPTOR_ACCESSED, KGDT_DPL_USER, 2);
|
||||||
|
XtpInitializeGdtEntry(GdtEntry, KGDT_R0_LDT, 0x0, 0x0, 0, KGDT_DPL_SYSTEM, 0);
|
||||||
|
XtpInitializeGdtEntry(GdtEntry, KGDT_VDM_TILE, 0x0400, 0xFFFF, KGDT_TYPE_DATA, KGDT_DPL_USER, 0);
|
||||||
|
XtpInitializeGdtEntry(GdtEntry, KGDT_R0_PCR, (ULONG_PTR)Pcr, 0x1, KGDT_TYPE_DATA, KGDT_DPL_SYSTEM, 2);
|
||||||
|
XtpInitializeGdtEntry(GdtEntry, KGDT_SYS_TSS, (ULONG_PTR)Tss, sizeof(KTSS) - 1, I686_TSS, KGDT_DPL_SYSTEM, 0);
|
||||||
|
XtpInitializeGdtEntry(GdtEntry, KGDT_DF_TSS, 0x20000, 0xFFFF, I686_TSS, KGDT_DPL_SYSTEM, 0);
|
||||||
|
XtpInitializeGdtEntry(GdtEntry, KGDT_NMI_TSS, 0x20000, 0xFFFF, KGDT_TYPE_CODE, KGDT_DPL_SYSTEM, 0);
|
||||||
|
|
||||||
|
/* Map GDT and set its virtual address */
|
||||||
|
Status = XtLdrProtocol->AddVirtualMemoryMapping(MemoryMappings, *VirtualAddress, GdtEntry,
|
||||||
|
EFI_SIZE_TO_PAGES(128 * sizeof(KGDTENTRY)), LoaderMemoryData);
|
||||||
|
*Gdt = (PKGDTENTRY)*VirtualAddress;
|
||||||
|
|
||||||
|
/* Set next valid virtual address */
|
||||||
|
*VirtualAddress += (EFI_SIZE_TO_PAGES(128 * sizeof(KGDTENTRY)) * EFI_PAGE_SIZE);
|
||||||
|
|
||||||
|
/* Return success */
|
||||||
|
return STATUS_EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads previously prepared CPU context and performs architecture-specific tasks needed to boot XTOS.
|
||||||
|
*
|
||||||
|
* @param Gdt
|
||||||
|
* Supplies a pointer to memory area containing GDT to load.
|
||||||
|
*
|
||||||
|
* @return This routine does not return any value.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTCDECL
|
||||||
|
VOID
|
||||||
|
XtpLoadProcessorContext(IN PKGDTENTRY Gdt)
|
||||||
|
{
|
||||||
|
KDESCRIPTOR GdtDescriptor;
|
||||||
|
|
||||||
|
GdtDescriptor.Base = (PVOID)(ULONG_PTR)Gdt;
|
||||||
|
GdtDescriptor.Limit = 128 * sizeof(KGDTENTRY) - 1;
|
||||||
|
|
||||||
|
/* Load GDT and TSS */
|
||||||
|
HlLoadGlobalDescriptorTable(&GdtDescriptor.Limit);
|
||||||
|
HlLoadTaskRegister((UINT32)KGDT_SYS_TSS);
|
||||||
|
|
||||||
|
/* Load PCR in FS segment */
|
||||||
|
HlLoadSegment(SEGMENT_FS, KGDT_R0_PCR);
|
||||||
|
|
||||||
|
/* Re-enable IDE interrupts */
|
||||||
|
HlIoPortOutByte(0x376, 0);
|
||||||
|
HlIoPortOutByte(0x3F6, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets architecture specific processor context.
|
||||||
|
*
|
||||||
|
* @param MemoryMappings
|
||||||
|
* Supplies a pointer to linked list containing all memory mappings.
|
||||||
|
*
|
||||||
|
* @param VirtualAddress
|
||||||
|
* Supplies a pointer to the next valid, free and available virtual address.
|
||||||
|
*
|
||||||
|
* @param Gdt
|
||||||
|
* Supplies a pointer to memory area containing GDT to fill in.
|
||||||
|
*
|
||||||
|
* @return This routine returns a status code.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTCDECL
|
||||||
|
EFI_STATUS
|
||||||
|
XtpSetProcessorContext(IN PLIST_ENTRY MemoryMappings,
|
||||||
|
IN PVOID *VirtualAddress,
|
||||||
|
OUT PKGDTENTRY *Gdt)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
/* Print debug message */
|
||||||
|
XtLdrProtocol->DbgPrint(L"Setting processor context\n");
|
||||||
|
|
||||||
|
/* Disable interrupts */
|
||||||
|
HlClearInterruptFlag();
|
||||||
|
|
||||||
|
/* Initialize GDT */
|
||||||
|
Status = XtpInitializeDescriptors(MemoryMappings, VirtualAddress, Gdt);
|
||||||
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
|
{
|
||||||
|
/* GDT initialization failure */
|
||||||
|
XtLdrProtocol->DbgPrint(L"Failed to initialize GDT (Status Code: %lx)\n", Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return success */
|
||||||
|
return STATUS_EFI_SUCCESS;
|
||||||
|
}
|
@ -12,6 +12,9 @@
|
|||||||
#include <blmod.h>
|
#include <blmod.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* EFI XT Loader Protocol */
|
||||||
|
EXTERN PXT_BOOT_LOADER_PROTOCOL XtLdrProtocol;
|
||||||
|
|
||||||
/* XTOS kernel entry point */
|
/* XTOS kernel entry point */
|
||||||
typedef VOID (XTAPI *PXT_ENTRY_POINT)(IN PKERNEL_INITIALIZATION_BLOCK BootParameters);
|
typedef VOID (XTAPI *PXT_ENTRY_POINT)(IN PKERNEL_INITIALIZATION_BLOCK BootParameters);
|
||||||
|
|
||||||
@ -25,6 +28,22 @@ EFI_STATUS
|
|||||||
XtpBootSequence(IN PEFI_FILE_HANDLE BootDir,
|
XtpBootSequence(IN PEFI_FILE_HANDLE BootDir,
|
||||||
IN PXT_BOOT_PROTOCOL_PARAMETERS Parameters);
|
IN PXT_BOOT_PROTOCOL_PARAMETERS Parameters);
|
||||||
|
|
||||||
|
XTCDECL
|
||||||
|
VOID
|
||||||
|
XtpInitializeGdtEntry(IN PKGDTENTRY Gdt,
|
||||||
|
IN USHORT Selector,
|
||||||
|
IN ULONGLONG Base,
|
||||||
|
IN ULONG Limit,
|
||||||
|
IN UCHAR Type,
|
||||||
|
IN UCHAR Dpl,
|
||||||
|
IN UCHAR SegmentMode);
|
||||||
|
|
||||||
|
XTCDECL
|
||||||
|
EFI_STATUS
|
||||||
|
XtpInitializeDescriptors(IN PLIST_ENTRY MemoryMappings,
|
||||||
|
IN PVOID *VirtualAddress,
|
||||||
|
OUT PKGDTENTRY *Gdt);
|
||||||
|
|
||||||
XTCDECL
|
XTCDECL
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
XtpInitializeLoaderBlock(IN PLIST_ENTRY MemoryMappings,
|
XtpInitializeLoaderBlock(IN PLIST_ENTRY MemoryMappings,
|
||||||
@ -38,6 +57,16 @@ XtpLoadModule(IN PEFI_FILE_HANDLE BootDir,
|
|||||||
IN LOADER_MEMORY_TYPE MemoryType,
|
IN LOADER_MEMORY_TYPE MemoryType,
|
||||||
OUT PPECOFF_IMAGE_CONTEXT *ImageContext);
|
OUT PPECOFF_IMAGE_CONTEXT *ImageContext);
|
||||||
|
|
||||||
|
XTCDECL
|
||||||
|
VOID
|
||||||
|
XtpLoadProcessorContext(IN PKGDTENTRY Gdt);
|
||||||
|
|
||||||
|
XTCDECL
|
||||||
|
EFI_STATUS
|
||||||
|
XtpSetProcessorContext(IN PLIST_ENTRY MemoryMappings,
|
||||||
|
IN PVOID *VirtualAddress,
|
||||||
|
OUT PKGDTENTRY *Gdt);
|
||||||
|
|
||||||
XTCDECL
|
XTCDECL
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
BlXtLdrModuleMain(IN EFI_HANDLE ImageHandle,
|
BlXtLdrModuleMain(IN EFI_HANDLE ImageHandle,
|
||||||
|
@ -188,6 +188,7 @@ XtpBootSequence(IN PEFI_FILE_HANDLE BootDir,
|
|||||||
LIST_ENTRY MemoryMappings;
|
LIST_ENTRY MemoryMappings;
|
||||||
ULONG KernelStackPages;
|
ULONG KernelStackPages;
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
|
PKGDTENTRY Gdt;
|
||||||
|
|
||||||
/* Initialize XTOS startup sequence */
|
/* Initialize XTOS startup sequence */
|
||||||
XtLdrProtocol->DbgPrint(L"Initializing XTOS startup sequence\n");
|
XtLdrProtocol->DbgPrint(L"Initializing XTOS startup sequence\n");
|
||||||
@ -257,6 +258,15 @@ XtpBootSequence(IN PEFI_FILE_HANDLE BootDir,
|
|||||||
KernelStackPages, LoaderStartupKernelStack);
|
KernelStackPages, LoaderStartupKernelStack);
|
||||||
VirtualAddress += (KernelStackPages * EFI_PAGE_SIZE);
|
VirtualAddress += (KernelStackPages * EFI_PAGE_SIZE);
|
||||||
|
|
||||||
|
/* Set processor context */
|
||||||
|
Status = XtpSetProcessorContext(&MemoryMappings, &VirtualAddress, &Gdt);
|
||||||
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Failed to set processor context */
|
||||||
|
XtLdrProtocol->DbgPrint(L"Failed to set processor context (Status Code: %lx)\n", Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
/* Enable paging */
|
/* Enable paging */
|
||||||
EfiSystemTable->BootServices->HandleProtocol(EfiImageHandle, &LoadedImageGuid, (PVOID*)&ImageProtocol);
|
EfiSystemTable->BootServices->HandleProtocol(EfiImageHandle, &LoadedImageGuid, (PVOID*)&ImageProtocol);
|
||||||
Status = XtLdrProtocol->EnablePaging(&MemoryMappings, VirtualAddress, ImageProtocol, &XtPageMap);
|
Status = XtLdrProtocol->EnablePaging(&MemoryMappings, VirtualAddress, ImageProtocol, &XtPageMap);
|
||||||
@ -267,6 +277,9 @@ XtpBootSequence(IN PEFI_FILE_HANDLE BootDir,
|
|||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Load processor context */
|
||||||
|
XtpLoadProcessorContext(Gdt);
|
||||||
|
|
||||||
/* Call XTOS kernel */
|
/* Call XTOS kernel */
|
||||||
XtLdrProtocol->DbgPrint(L"Booting the XTOS kernel\n");
|
XtLdrProtocol->DbgPrint(L"Booting the XTOS kernel\n");
|
||||||
KernelEntryPoint(KernelParameters);
|
KernelEntryPoint(KernelParameters);
|
||||||
|
Loading…
Reference in New Issue
Block a user