Created
October 16, 2024 16:29
-
-
Save hlgsdx/d5d356509c5eb2cd7bb281c4d9240aa3 to your computer and use it in GitHub Desktop.
Revisions
-
hlgsdx created this gist
Oct 16, 2024 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,191 @@ #include <Uefi.h> #include <Library/UefiBootServicesTableLib.h> #include <Library/UefiRuntimeServicesTableLib.h> #include <Library/UefiLib.h> #include <Library/MemoryAllocationLib.h> #include <Protocol/SimpleFileSystem.h> #include <Protocol/LoadFile.h> #include <Guid/FileInfo.h> #include <Library/BaseLib.h> #include <Library/PrintLib.h> #include <Protocol/LoadedImage.h> // 加载EFI_LOADED_IMAGE_PROTOCOL #include <Library/DevicePathLib.h> // FileDevicePath 函数所在的库 // Windows Boot Loader的路径 #define WINDOWS_BOOT_LOADER_PATH L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi" // 用于存放时间戳文件的路径 #define TIME_SYNC_FILE L"timestamp.txt" // Function to convert Unix timestamp to EFI_TIME structure VOID ConvertUnixTimeToEfiTime(UINT64 UnixTime, EFI_TIME *EfiTime) { EfiTime->Year = 1970 + (UnixTime / 31556926); // 大致按年计算 UnixTime %= 31556926; EfiTime->Month = 1 + (UnixTime / 2629743); UnixTime %= 2629743; EfiTime->Day = 1 + (UnixTime / 86400); UnixTime %= 86400; EfiTime->Hour = (UINT8)(UnixTime / 3600); UnixTime %= 3600; EfiTime->Minute = (UINT8)(UnixTime / 60); EfiTime->Second = (UINT8)(UnixTime % 60); EfiTime->Nanosecond = 0; EfiTime->TimeZone = EFI_UNSPECIFIED_TIMEZONE; EfiTime->Daylight = 0; } // Function to print EFI_TIME in yyyy-mm-dd hh:mm:ss format VOID PrintEfiTime(EFI_TIME *Time) { Print(L"%04u-%02u-%02u %02u:%02u:%02u\n", Time->Year, Time->Month, Time->Day, Time->Hour, Time->Minute, Time->Second); } // Function to read the timestamp file and update the system time EFI_STATUS SyncTimeFromFile(EFI_HANDLE ImageHandle) { EFI_STATUS Status; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFileSystem; EFI_FILE_PROTOCOL *Root; EFI_FILE_PROTOCOL *File; UINTN BufferSize; CHAR8 Buffer[64]; // 假设文件中的64位时间戳不会超过64字节 // 1. Locate the EFI partition Status = gBS->LocateProtocol(&gEfiSimpleFileSystemProtocolGuid, NULL, (VOID **)&SimpleFileSystem); if (EFI_ERROR(Status)) { Print(L"Failed to locate Simple File System Protocol: %r\n", Status); return Status; } // 2. Open the root directory of the EFI partition Status = SimpleFileSystem->OpenVolume(SimpleFileSystem, &Root); if (EFI_ERROR(Status)) { Print(L"Failed to open EFI partition root: %r\n", Status); return Status; } // 3. Open the timestamp file Status = Root->Open(Root, &File, TIME_SYNC_FILE, EFI_FILE_MODE_READ, 0); if (EFI_ERROR(Status)) { Print(L"Failed to open timestamp file: %r\n", Status); return Status; } // 4. Read the timestamp from the file BufferSize = sizeof(Buffer); Status = File->Read(File, &BufferSize, Buffer); if (EFI_ERROR(Status) || BufferSize == 0) { Print(L"Failed to read timestamp file: %r\n", Status); File->Close(File); return Status; } Buffer[BufferSize] = '\0'; // 确保字符串结尾 UINT64 UnixTime = AsciiStrDecimalToUint64(Buffer); // Close the file File->Close(File); // 5. Convert Unix timestamp to EFI_TIME structure EFI_TIME NewTime; ConvertUnixTimeToEfiTime(UnixTime, &NewTime); // 6. Set the UEFI system time Status = gRT->SetTime(&NewTime); if (EFI_ERROR(Status)) { Print(L"Failed to set system time: %r\n", Status); PrintEfiTime(&NewTime); return Status; } Print(L"System time updated successfully.\n"); return EFI_SUCCESS; } // Function to chainload Windows Boot Loader EFI_STATUS ChainloadWindowsBootLoader(EFI_HANDLE ImageHandle) { EFI_STATUS Status; EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; EFI_DEVICE_PATH_PROTOCOL *DevicePath; EFI_HANDLE BootLoaderHandle; // 1. Locate the Windows Boot Loader path on the EFI partition Status = gBS->HandleProtocol(ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&LoadedImage); if (EFI_ERROR(Status)) { Print(L"Failed to locate loaded image protocol: %r\n", Status); return Status; } // Use FileDevicePath to get the device path for Windows Boot Loader DevicePath = FileDevicePath(LoadedImage->DeviceHandle, WINDOWS_BOOT_LOADER_PATH); if (DevicePath == NULL) { Print(L"Failed to locate Windows Boot Loader path.\n"); return EFI_NOT_FOUND; } // 2. Load the Windows Boot Loader Status = gBS->LoadImage(FALSE, ImageHandle, DevicePath, NULL, 0, &BootLoaderHandle); if (EFI_ERROR(Status)) { Print(L"Failed to load Windows Boot Loader: %r\n", Status); return Status; } // 3. Start the Windows Boot Loader Status = gBS->StartImage(BootLoaderHandle, NULL, NULL); if (EFI_ERROR(Status)) { Print(L"Failed to start Windows Boot Loader: %r\n", Status); return Status; } // Should never return return EFI_SUCCESS; } // Entry point of the UEFI application EFI_STATUS EFIAPI UefiMain(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable) { EFI_STATUS Status; EFI_TIME CurrentTime; Print(L"Time Synchronization Application Started\n"); // 1. Get and print the current system time Status = gRT->GetTime(&CurrentTime, NULL); if (EFI_ERROR(Status)) { Print(L"Failed to get current time: %r\n", Status); } else { Print(L"Current System Time: "); PrintEfiTime(&CurrentTime); } // 2. Sync time from the file Status = SyncTimeFromFile(ImageHandle); if (EFI_ERROR(Status)) { Print(L"Failed to synchronize time: %r\n", Status); } // 3. Get and print the updated system time Status = gRT->GetTime(&CurrentTime, NULL); if (EFI_ERROR(Status)) { Print(L"Failed to get updated time: %r\n", Status); } else { Print(L"Updated System Time: "); PrintEfiTime(&CurrentTime); } // Wait 3 sec gBS->Stall(3000000); // 4. Chainload the Windows Boot Loader Status = ChainloadWindowsBootLoader(ImageHandle); if (EFI_ERROR(Status)) { Print(L"Failed to chainload Windows Boot Loader: %r\n", Status); } return Status; } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,26 @@ [Defines] INF_VERSION = 0x00010005 BASE_NAME = TimeInitDemo FILE_GUID = 64c8307f-b5ec-47da-85c8-efb8de1a3f66 MODULE_TYPE = UEFI_APPLICATION VERSION_STRING = 1.0 ENTRY_POINT = UefiMain [Sources] TimeInitDemo.c [Packages] MdePkg/MdePkg.dec [LibraryClasses] UefiApplicationEntryPoint UefiLib UefiBootServicesTableLib UefiRuntimeServicesTableLib MemoryAllocationLib BaseLib PrintLib DevicePathLib [Protocols] gEfiLoadedImageProtocolGuid