|
8 | 8 | **/ |
9 | 9 | #include "BlSupportDxe.h" |
10 | 10 |
|
| 11 | +#include <Protocol/DevicePath.h> |
| 12 | +#include <Library/DevicePathLib.h> |
| 13 | +#include <Protocol/RamDisk.h> |
| 14 | +#include <Library/MemoryAllocationLib.h> |
| 15 | + |
11 | 16 | /** |
12 | 17 | Reserve MMIO/IO resource in GCD |
13 | 18 |
|
@@ -80,6 +85,60 @@ ReserveResourceInGcd ( |
80 | 85 | } |
81 | 86 |
|
82 | 87 |
|
| 88 | +static void EFIAPI ramdisk_callback(EFI_EVENT event, void * context) |
| 89 | +{ |
| 90 | + const SYSTEM_TABLE_INFO *SystemTableInfo = context; |
| 91 | + const unsigned char * ramdisk_base = (const void*) SystemTableInfo->RamDiskBase; |
| 92 | + const UINTN ramdisk_size = SystemTableInfo->RamDiskSize; |
| 93 | + |
| 94 | + if (!ramdisk_base || !ramdisk_size) |
| 95 | + return; |
| 96 | + |
| 97 | + EFI_STATUS Status; |
| 98 | + EFI_RAM_DISK_PROTOCOL *RamDisk; |
| 99 | + EFI_DEVICE_PATH_PROTOCOL *DevicePath; |
| 100 | + EFI_GUID *RamDiskType = &gEfiVirtualDiskGuid; |
| 101 | + |
| 102 | + Status = gBS->LocateProtocol(&gEfiRamDiskProtocolGuid, NULL, (VOID**) &RamDisk); |
| 103 | + // if there is no protocol, we've been signalled too early. we'll try again later |
| 104 | + if (EFI_ERROR (Status)) |
| 105 | + return; |
| 106 | + |
| 107 | + // it is necessary to copy the ramdisk from the kexec allocated memory to uefi allocated |
| 108 | + // memory. otherwise the memory will be reclaimed during the boot process, leading to |
| 109 | + // a corrupt BCD hive or other propblems. |
| 110 | + const unsigned char * ramdisk_copy = AllocateCopyPool(ramdisk_size, (const void*) ramdisk_base); |
| 111 | + if (!ramdisk_copy) |
| 112 | + { |
| 113 | + DEBUG((EFI_D_ERROR, "allocate %d bytes for ramdisk copy failed\n", ramdisk_size)); |
| 114 | + return; |
| 115 | + } |
| 116 | + |
| 117 | +/* |
| 118 | + for(int i = 0x200 ; i < 0x240 ; i++) |
| 119 | + DEBUG ((EFI_D_INFO, "%02x", ramdisk_base[i])); |
| 120 | + DEBUG ((EFI_D_INFO, "\n")); |
| 121 | +*/ |
| 122 | + |
| 123 | + Status = RamDisk->Register( |
| 124 | + (UINTN) ramdisk_copy, |
| 125 | + ramdisk_size, |
| 126 | + RamDiskType, |
| 127 | + NULL, |
| 128 | + &DevicePath |
| 129 | + ); |
| 130 | + |
| 131 | + if (EFI_ERROR (Status)) { |
| 132 | + DEBUG ((EFI_D_ERROR, "ramdisk_setup: Failed to register RAM Disk - %r\n", Status)); |
| 133 | + return; |
| 134 | + } |
| 135 | + |
| 136 | + VOID * Temp = ConvertDevicePathToText(DevicePath, TRUE, TRUE); |
| 137 | + DEBUG ((EFI_D_INFO, "ramdisk_setup: ram disk %p + %x: device path %S\n", ramdisk_copy, ramdisk_size, Temp)); |
| 138 | + FreePool(Temp); |
| 139 | +} |
| 140 | + |
| 141 | + |
83 | 142 | /** |
84 | 143 | Main entry for the bootloader support DXE module. |
85 | 144 |
|
@@ -180,5 +239,16 @@ BlDxeEntryPoint ( |
180 | 239 | ASSERT_EFI_ERROR (Status); |
181 | 240 | } |
182 | 241 |
|
| 242 | + // Wait for the RamDiskProtocol to become available |
| 243 | + static EFI_EVENT ramdisk_event; |
| 244 | + static void * ramdisk_registration; |
| 245 | + |
| 246 | + Status = gBS->CreateEvent(EVT_NOTIFY_SIGNAL, TPL_CALLBACK, ramdisk_callback, SystemTableInfo, &ramdisk_event); |
| 247 | + ASSERT_EFI_ERROR(Status); |
| 248 | + Status = gBS->RegisterProtocolNotify(&gEfiRamDiskProtocolGuid, ramdisk_event, &ramdisk_registration); |
| 249 | + ASSERT_EFI_ERROR(Status); |
| 250 | + Status = gBS->SignalEvent(ramdisk_event); |
| 251 | + ASSERT_EFI_ERROR(Status); |
| 252 | + |
183 | 253 | return EFI_SUCCESS; |
184 | 254 | } |
0 commit comments