init.c
来自「Next BIOS Source code : Extensible Firmw」· C语言 代码 · 共 818 行 · 第 1/2 页
C
818 行
N.B. The FW requires that the first call be of type
"ConventialMemory".
N.B. The FW requires that page 0 in the map is not
not ConventialMemory. (Note the emulator can work
around this by reporting page 0 as BootServicesData
memory if needed. The page is then not used at
Boot Services time, but it available in the memory
map for later use)
Arguments:
None
Returns:
Memory map descriptors added
--*/
{
HANDLE File, Map;
VOID *View;
UINT32 MapSize;
//
// Map in a large chunk of memory, then provide it to the
// FW as our memory map
//
MapSize = 0x1400000; // 20mb of space
File = CreateFile(L"corefile", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL,OPEN_ALWAYS, 0, NULL);
Map = CreateFileMapping(File, NULL, PAGE_READWRITE, 0, MapSize, L"ntefi_core");
View = MapViewOfFileEx (Map, FILE_MAP_ALL_ACCESS, 0, 0, MapSize, NULL);
//
// Add some memory descriptors
//
FW->AddMemoryDescriptor (EfiConventionalMemory, (UINTN) View, MapSize / 4096, EFI_MEMORY_WB);
}
STATIC
VOID
PlInstallBaseDevices (
VOID
)
/*++
Routine Description:
Add handles to the base devices here. In particular
the console devices, internal nvram device(s), and
the timer tick handler.
Arguments:
None
Returns:
Base device handles added
--*/
{
EFI_DEVICE_PATH *DevicePath;
EFI_HANDLE Handle;
EFI_STATUS Status;
//
//
// First add a device(s) to handle device_io request
// (this is done since the next devices may need to access
// their IO space)
//
// On a PC there's only global IO, and the firwmare is
// nice enough to provide us with a driver that does just
// that... add it
PlInstallDefaultIoDevice (
BiosRootDevicePath,
0x0000000000000000, // Force non cachable access
0x0000000000000000
);
//
// Set up the GlobalIoFncs global to point to global memory/io/pci space
//
DevicePath = BiosRootDevicePath;
Status = BS->LocateDevicePath (&DeviceIoProtocol, &DevicePath, &Handle);
if (!EFI_ERROR(Status)) {
Status = BS->HandleProtocol (Handle, &DeviceIoProtocol, &GlobalIoFncs);
}
ASSERT (!EFI_ERROR(Status));
//
// Initialize to PCI Root Bus List
//
InitializePciRootBusList (&PciRootBusList);
//
// BUGBUG: add the timer tick handler here
//
//
// Add the internal NvRam device
//
PlInitNvVarStoreEmul (
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
0x4000, 2
);
//
// Install the Unicode string device. This device supports
// case insensitive comparisons of Unicode strings.
//
PlInitializeUnicodeStringDevice();
}
STATIC
VOID
PlExitBootServices (
IN EFI_EVENT Event,
IN VOID *Context
)
{
//
// Clear non-runtime pointer
//
PlTable.EmulateLoad = NULL;
PlTable.IdleLoop = NULL;
PlTable.SetInterruptState = NULL;
// EFI f/w takes care of boot service's table
}
STATIC
VOID
PlSetVirtualMapping (
IN EFI_EVENT Event,
IN VOID *Context
)
{
EFI_CONVERT_POINTER ConvertPointer;
//
// Different components are updating themselves to work in the
// new memory mappings. The only function that is safe to call
// during this notification is ConvertPointer.
//
ConvertPointer = RT->ConvertPointer;
//
// Fix any runtime pointers
//
//
// Notify Lib of change
//
RtLibEnableVirtualMappings ();
}
VOID
PlInstallSignalHandlers (
VOID
)
{
EFI_STATUS Status;
EFI_EVENT Event;
//
// Create an event to be signalled when ExitBootServices occurs
//
Status = BS->CreateEvent(
EVT_SIGNAL_EXIT_BOOT_SERVICES,
TPL_NOTIFY,
PlExitBootServices,
NULL,
&Event
);
ASSERT (!EFI_ERROR(Status));
//
// Create an event to be signalled when SetVirtualAddressMap occurs
// N.B. We must pass the "runtime" table pointer to use during the
// notification
//
Status = BS->CreateEvent(
EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,
TPL_NOTIFY,
PlSetVirtualMapping,
NULL,
&Event
);
ASSERT (!EFI_ERROR(Status));
}
VOID
PlIdleLoop (
IN BOOLEAN Polling
)
{
Sleep(5);
}
BOOLEAN
PlSetInterruptState (
IN BOOLEAN Enable
)
{
BOOLEAN PreviousState;
PreviousState = NtInterruptState;
NtInterruptState = Enable;
return PreviousState;
}
STATIC
VOID
PlSetVirtualAddressMap (
IN EFI_CONVERT_POINTER ConvertPointer,
IN UINTN MemoryMapSize,
IN UINTN DescriptorSize,
IN UINT32 DescriptorVersion,
IN EFI_MEMORY_DESCRIPTOR *VirtualMap
)
{
// fyi.. can't use DEBUG print in here because everyhting but
// the base firmware has been fixedup for virtual mode
}
STATIC
EFI_STATUS
PlStall(
IN UINTN Microseconds
)
{
UINTN ms;
ms = Microseconds / 1000 + (Microseconds % 1000 ? 1 : 0);
Sleep(ms);
return EFI_SUCCESS;
}
#define TIMER_TICK_DURATION 10
STATIC HANDLE hMainThread;
DWORD WINAPI
TimerThread(
LPVOID lpParameter // thread data
)
{
EFI_TPL OriginalTPL;
DWORD CurrentTick, Delta;
//
// Set our thread priority higher than the "main" thread.
//
if (!SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_HIGHEST))
printf("SetThreadPriority(HIGH) returned %d\n", GetLastError());
while (1) {
//
// Wait the appropriate interval
//
Sleep( TIMER_TICK_DURATION );
//
// Suspend the main thread until we are done
//
(void)SuspendThread(hMainThread);
while (NtInterruptState == FALSE) {
//
// Resume the main thread
//
(void)ResumeThread(hMainThread);
//
// Wait for interrupts to be enabled.
//
while (NtInterruptState == FALSE)
Sleep(0);
//
// Suspend the main thread until we are done
//
(void)SuspendThread(hMainThread);
}
//
// Get the current system tick
//
CurrentTick = GetTickCount ();
Delta = CurrentTick - NtLastTick;
NtLastTick = CurrentTick;
//
// If delay was more then 1 second, pitch it (probably debugging)
//
if (Delta < 1000) {
OriginalTPL = BS->RaiseTPL (TPL_HIGH_LEVEL );
//
// Inform the firmware of an "timer interrupt". The time
// expired since the last call is 10,000 times the number
// of ms. (or 100ns units)
//
FW->TickHandler (Delta * 10000);
BS->RestoreTPL (OriginalTPL);
}
//
// Resume the main thread
//
(void)ResumeThread(hMainThread);
}
}
STATIC VOID
PlEnableTimerInterrupt(
VOID
)
{
HANDLE hTimerThread;
DWORD dwThreadId;
//
// Initialize timer interrupts
// (N.B. in the NT emulation environment we only need to get the
// starting tick location)
//
NtLastTick = GetTickCount();
//
// Get our handle so the timer tick thread can suspend us.
//
if (!DuplicateHandle(
GetCurrentProcess(), // handle to source process
GetCurrentThread(), // handle to duplicate
GetCurrentProcess(), // handle to target process
&hMainThread, // duplicate handle
0, // requested access
FALSE, // handle inheritance option
DUPLICATE_SAME_ACCESS // optional actions
)) {
printf("DuplicateHandle returned error %d\n", GetLastError());
return;
}
//
// Create a thread to simulate timer interrupts
//
hTimerThread = CreateThread(
NULL,
0,
TimerThread,
NULL,
0,
&dwThreadId );
if (hTimerThread == NULL) {
printf("Error %d creating TimerThread\n", GetLastError());
}
}
STATIC
EFI_STATUS
NtPlResetSystem (
IN EFI_RESET_TYPE ResetType,
IN EFI_STATUS ResetStatus,
IN UINTN DataSize,
IN CHAR16 *ResetData OPTIONAL
)
{
ExitProcess((UINT)ResetType);
return EFI_SUCCESS;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?