+++ /dev/null
-/** @file\r
- Implementation for PlatformBdsLib library class interfaces.\r
-\r
- Copyright (C) 2015, Red Hat, Inc.\r
- Copyright (c) 2014, ARM Ltd. All rights reserved.<BR>\r
- Copyright (c) 2004 - 2008, Intel Corporation. All rights reserved.<BR>\r
-\r
- This program and the accompanying materials are licensed and made available\r
- under the terms and conditions of the BSD License which accompanies this\r
- distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
- WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-**/\r
-\r
-#include <IndustryStandard/Pci22.h>\r
-#include <Library/DevicePathLib.h>\r
-#include <Library/PcdLib.h>\r
-#include <Library/PlatformBdsLib.h>\r
-#include <Library/QemuBootOrderLib.h>\r
-#include <Protocol/DevicePath.h>\r
-#include <Protocol/GraphicsOutput.h>\r
-#include <Protocol/PciIo.h>\r
-#include <Protocol/PciRootBridgeIo.h>\r
-#include <Guid/EventGroup.h>\r
-#include <Guid/RootBridgesConnectedEventGroup.h>\r
-\r
-#include "IntelBdsPlatform.h"\r
-\r
-#define DP_NODE_LEN(Type) { (UINT8)sizeof (Type), (UINT8)(sizeof (Type) >> 8) }\r
-\r
-\r
-#pragma pack (1)\r
-typedef struct {\r
- VENDOR_DEVICE_PATH SerialDxe;\r
- UART_DEVICE_PATH Uart;\r
- VENDOR_DEFINED_DEVICE_PATH TermType;\r
- EFI_DEVICE_PATH_PROTOCOL End;\r
-} PLATFORM_SERIAL_CONSOLE;\r
-#pragma pack ()\r
-\r
-#define SERIAL_DXE_FILE_GUID { \\r
- 0xD3987D4B, 0x971A, 0x435F, \\r
- { 0x8C, 0xAF, 0x49, 0x67, 0xEB, 0x62, 0x72, 0x41 } \\r
- }\r
-\r
-STATIC PLATFORM_SERIAL_CONSOLE mSerialConsole = {\r
- //\r
- // VENDOR_DEVICE_PATH SerialDxe\r
- //\r
- {\r
- { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, DP_NODE_LEN (VENDOR_DEVICE_PATH) },\r
- SERIAL_DXE_FILE_GUID\r
- },\r
-\r
- //\r
- // UART_DEVICE_PATH Uart\r
- //\r
- {\r
- { MESSAGING_DEVICE_PATH, MSG_UART_DP, DP_NODE_LEN (UART_DEVICE_PATH) },\r
- 0, // Reserved\r
- FixedPcdGet64 (PcdUartDefaultBaudRate), // BaudRate\r
- FixedPcdGet8 (PcdUartDefaultDataBits), // DataBits\r
- FixedPcdGet8 (PcdUartDefaultParity), // Parity\r
- FixedPcdGet8 (PcdUartDefaultStopBits) // StopBits\r
- },\r
-\r
- //\r
- // VENDOR_DEFINED_DEVICE_PATH TermType\r
- //\r
- {\r
- {\r
- MESSAGING_DEVICE_PATH, MSG_VENDOR_DP,\r
- DP_NODE_LEN (VENDOR_DEFINED_DEVICE_PATH)\r
- }\r
- //\r
- // Guid to be filled in dynamically\r
- //\r
- },\r
-\r
- //\r
- // EFI_DEVICE_PATH_PROTOCOL End\r
- //\r
- {\r
- END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
- DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL)\r
- }\r
-};\r
-\r
-\r
-#pragma pack (1)\r
-typedef struct {\r
- USB_CLASS_DEVICE_PATH Keyboard;\r
- EFI_DEVICE_PATH_PROTOCOL End;\r
-} PLATFORM_USB_KEYBOARD;\r
-#pragma pack ()\r
-\r
-STATIC PLATFORM_USB_KEYBOARD mUsbKeyboard = {\r
- //\r
- // USB_CLASS_DEVICE_PATH Keyboard\r
- //\r
- {\r
- {\r
- MESSAGING_DEVICE_PATH, MSG_USB_CLASS_DP,\r
- DP_NODE_LEN (USB_CLASS_DEVICE_PATH)\r
- },\r
- 0xFFFF, // VendorId: any\r
- 0xFFFF, // ProductId: any\r
- 3, // DeviceClass: HID\r
- 1, // DeviceSubClass: boot\r
- 1 // DeviceProtocol: keyboard\r
- },\r
-\r
- //\r
- // EFI_DEVICE_PATH_PROTOCOL End\r
- //\r
- {\r
- END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
- DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL)\r
- }\r
-};\r
-\r
-//\r
-// BDS Platform Functions\r
-//\r
-/**\r
- Platform Bds init. Include the platform firmware vendor, revision\r
- and so crc check.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-PlatformBdsInit (\r
- VOID\r
- )\r
-{\r
- //\r
- // Signal EndOfDxe PI Event\r
- //\r
- EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);\r
-}\r
-\r
-\r
-/**\r
- Check if the handle satisfies a particular condition.\r
-\r
- @param[in] Handle The handle to check.\r
- @param[in] ReportText A caller-allocated string passed in for reporting\r
- purposes. It must never be NULL.\r
-\r
- @retval TRUE The condition is satisfied.\r
- @retval FALSE Otherwise. This includes the case when the condition could not\r
- be fully evaluated due to an error.\r
-**/\r
-typedef\r
-BOOLEAN\r
-(EFIAPI *FILTER_FUNCTION) (\r
- IN EFI_HANDLE Handle,\r
- IN CONST CHAR16 *ReportText\r
- );\r
-\r
-\r
-/**\r
- Process a handle.\r
-\r
- @param[in] Handle The handle to process.\r
- @param[in] ReportText A caller-allocated string passed in for reporting\r
- purposes. It must never be NULL.\r
-**/\r
-typedef\r
-VOID\r
-(EFIAPI *CALLBACK_FUNCTION) (\r
- IN EFI_HANDLE Handle,\r
- IN CONST CHAR16 *ReportText\r
- );\r
-\r
-/**\r
- Locate all handles that carry the specified protocol, filter them with a\r
- callback function, and pass each handle that passes the filter to another\r
- callback.\r
-\r
- @param[in] ProtocolGuid The protocol to look for.\r
-\r
- @param[in] Filter The filter function to pass each handle to. If this\r
- parameter is NULL, then all handles are processed.\r
-\r
- @param[in] Process The callback function to pass each handle to that\r
- clears the filter.\r
-**/\r
-STATIC\r
-VOID\r
-FilterAndProcess (\r
- IN EFI_GUID *ProtocolGuid,\r
- IN FILTER_FUNCTION Filter OPTIONAL,\r
- IN CALLBACK_FUNCTION Process\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_HANDLE *Handles;\r
- UINTN NoHandles;\r
- UINTN Idx;\r
-\r
- Status = gBS->LocateHandleBuffer (ByProtocol, ProtocolGuid,\r
- NULL /* SearchKey */, &NoHandles, &Handles);\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // This is not an error, just an informative condition.\r
- //\r
- DEBUG ((EFI_D_VERBOSE, "%a: %g: %r\n", __FUNCTION__, ProtocolGuid,\r
- Status));\r
- return;\r
- }\r
-\r
- ASSERT (NoHandles > 0);\r
- for (Idx = 0; Idx < NoHandles; ++Idx) {\r
- CHAR16 *DevicePathText;\r
- STATIC CHAR16 Fallback[] = L"<device path unavailable>";\r
-\r
- //\r
- // The ConvertDevicePathToText() function handles NULL input transparently.\r
- //\r
- DevicePathText = ConvertDevicePathToText (\r
- DevicePathFromHandle (Handles[Idx]),\r
- FALSE, // DisplayOnly\r
- FALSE // AllowShortcuts\r
- );\r
- if (DevicePathText == NULL) {\r
- DevicePathText = Fallback;\r
- }\r
-\r
- if (Filter == NULL || Filter (Handles[Idx], DevicePathText)) {\r
- Process (Handles[Idx], DevicePathText);\r
- }\r
-\r
- if (DevicePathText != Fallback) {\r
- FreePool (DevicePathText);\r
- }\r
- }\r
- gBS->FreePool (Handles);\r
-}\r
-\r
-\r
-/**\r
- This FILTER_FUNCTION checks if a handle corresponds to a PCI display device.\r
-**/\r
-STATIC\r
-BOOLEAN\r
-EFIAPI\r
-IsPciDisplay (\r
- IN EFI_HANDLE Handle,\r
- IN CONST CHAR16 *ReportText\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_PCI_IO_PROTOCOL *PciIo;\r
- PCI_TYPE00 Pci;\r
-\r
- Status = gBS->HandleProtocol (Handle, &gEfiPciIoProtocolGuid,\r
- (VOID**)&PciIo);\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // This is not an error worth reporting.\r
- //\r
- return FALSE;\r
- }\r
-\r
- Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0 /* Offset */,\r
- sizeof Pci / sizeof (UINT32), &Pci);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "%a: %s: %r\n", __FUNCTION__, ReportText, Status));\r
- return FALSE;\r
- }\r
-\r
- return IS_PCI_DISPLAY (&Pci);\r
-}\r
-\r
-\r
-/**\r
- This CALLBACK_FUNCTION attempts to connect a handle non-recursively, asking\r
- the matching driver to produce all first-level child handles.\r
-**/\r
-STATIC\r
-VOID\r
-EFIAPI\r
-Connect (\r
- IN EFI_HANDLE Handle,\r
- IN CONST CHAR16 *ReportText\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- Status = gBS->ConnectController (\r
- Handle, // ControllerHandle\r
- NULL, // DriverImageHandle\r
- NULL, // RemainingDevicePath -- produce all children\r
- FALSE // Recursive\r
- );\r
- DEBUG ((EFI_ERROR (Status) ? EFI_D_ERROR : EFI_D_VERBOSE, "%a: %s: %r\n",\r
- __FUNCTION__, ReportText, Status));\r
-}\r
-\r
-\r
-/**\r
- This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from the\r
- handle, and adds it to ConOut and ErrOut.\r
-**/\r
-STATIC\r
-VOID\r
-EFIAPI\r
-AddOutput (\r
- IN EFI_HANDLE Handle,\r
- IN CONST CHAR16 *ReportText\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
-\r
- DevicePath = DevicePathFromHandle (Handle);\r
- if (DevicePath == NULL) {\r
- DEBUG ((EFI_D_ERROR, "%a: %s: handle %p: device path not found\n",\r
- __FUNCTION__, ReportText, Handle));\r
- return;\r
- }\r
-\r
- Status = BdsLibUpdateConsoleVariable (L"ConOut", DevicePath, NULL);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "%a: %s: adding to ConOut: %r\n", __FUNCTION__,\r
- ReportText, Status));\r
- return;\r
- }\r
-\r
- Status = BdsLibUpdateConsoleVariable (L"ErrOut", DevicePath, NULL);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "%a: %s: adding to ErrOut: %r\n", __FUNCTION__,\r
- ReportText, Status));\r
- return;\r
- }\r
-\r
- DEBUG ((EFI_D_VERBOSE, "%a: %s: added to ConOut and ErrOut\n", __FUNCTION__,\r
- ReportText));\r
-}\r
-\r
-\r
-/**\r
- The function will execute with as the platform policy, current policy\r
- is driven by boot mode. IBV/OEM can customize this code for their specific\r
- policy action.\r
-\r
- @param DriverOptionList The header of the driver option link list\r
- @param BootOptionList The header of the boot option link list\r
- @param ProcessCapsules A pointer to ProcessCapsules()\r
- @param BaseMemoryTest A pointer to BaseMemoryTest()\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-PlatformBdsPolicyBehavior (\r
- IN LIST_ENTRY *DriverOptionList,\r
- IN LIST_ENTRY *BootOptionList,\r
- IN PROCESS_CAPSULES ProcessCapsules,\r
- IN BASEM_MEMORY_TEST BaseMemoryTest\r
- )\r
-{\r
- //\r
- // Locate the PCI root bridges and make the PCI bus driver connect each,\r
- // non-recursively. This will produce a number of child handles with PciIo on\r
- // them.\r
- //\r
- FilterAndProcess (&gEfiPciRootBridgeIoProtocolGuid, NULL, Connect);\r
-\r
- //\r
- // Signal the ACPI platform driver that it can download QEMU ACPI tables.\r
- //\r
- EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid);\r
-\r
- //\r
- // Find all display class PCI devices (using the handles from the previous\r
- // step), and connect them non-recursively. This should produce a number of\r
- // child handles with GOPs on them.\r
- //\r
- FilterAndProcess (&gEfiPciIoProtocolGuid, IsPciDisplay, Connect);\r
-\r
- //\r
- // Now add the device path of all handles with GOP on them to ConOut and\r
- // ErrOut.\r
- //\r
- FilterAndProcess (&gEfiGraphicsOutputProtocolGuid, NULL, AddOutput);\r
-\r
- //\r
- // Add the hardcoded short-form USB keyboard device path to ConIn.\r
- //\r
- BdsLibUpdateConsoleVariable (L"ConIn",\r
- (EFI_DEVICE_PATH_PROTOCOL *)&mUsbKeyboard, NULL);\r
-\r
- //\r
- // Add the hardcoded serial console device path to ConIn, ConOut, ErrOut.\r
- //\r
- CopyGuid (&mSerialConsole.TermType.Guid,\r
- PcdGetPtr (PcdTerminalTypeGuidBuffer));\r
- BdsLibUpdateConsoleVariable (L"ConIn",\r
- (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL);\r
- BdsLibUpdateConsoleVariable (L"ConOut",\r
- (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL);\r
- BdsLibUpdateConsoleVariable (L"ErrOut",\r
- (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL);\r
-\r
- //\r
- // Connect the consoles based on the above variables.\r
- //\r
- BdsLibConnectAllDefaultConsoles ();\r
-\r
- //\r
- // Show the splash screen.\r
- //\r
- EnableQuietBoot (PcdGetPtr (PcdLogoFile));\r
-\r
- //\r
- // Connect the rest of the devices.\r
- //\r
- BdsLibConnectAll ();\r
-\r
- //\r
- // Process QEMU's -kernel command line option. Note that the kernel booted\r
- // this way should receive ACPI tables, which is why we connect all devices\r
- // first (see above) -- PCI enumeration blocks ACPI table installation, if\r
- // there is a PCI host.\r
- //\r
- TryRunningQemuKernel ();\r
-\r
- BdsLibEnumerateAllBootOption (BootOptionList);\r
- SetBootOrderFromQemu (BootOptionList);\r
- //\r
- // The BootOrder variable may have changed, reload the in-memory list with\r
- // it.\r
- //\r
- BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder");\r
-\r
- PlatformBdsEnterFrontPage (GetFrontPageTimeoutFromQemu(), TRUE);\r
-}\r
-\r
-/**\r
- Hook point after a boot attempt succeeds. We don't expect a boot option to\r
- return, so the UEFI 2.0 specification defines that you will default to an\r
- interactive mode and stop processing the BootOrder list in this case. This\r
- is also a platform implementation and can be customized by IBV/OEM.\r
-\r
- @param Option Pointer to Boot Option that succeeded to boot.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-PlatformBdsBootSuccess (\r
- IN BDS_COMMON_OPTION *Option\r
- )\r
-{\r
-}\r
-\r
-/**\r
- Hook point after a boot attempt fails.\r
-\r
- @param Option Pointer to Boot Option that failed to boot.\r
- @param Status Status returned from failed boot.\r
- @param ExitData Exit data returned from failed boot.\r
- @param ExitDataSize Exit data size returned from failed boot.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-PlatformBdsBootFail (\r
- IN BDS_COMMON_OPTION *Option,\r
- IN EFI_STATUS Status,\r
- IN CHAR16 *ExitData,\r
- IN UINTN ExitDataSize\r
- )\r
-{\r
-}\r
-\r
-/**\r
- This function locks platform flash that is not allowed to be updated during normal boot path.\r
- The flash layout is platform specific.\r
-**/\r
-VOID\r
-EFIAPI\r
-PlatformBdsLockNonUpdatableFlash (\r
- VOID\r
- )\r
-{\r
- return;\r
-}\r
+++ /dev/null
-/** @file\r
- Try to load an EFI-stubbed ARM Linux kernel from QEMU's fw_cfg.\r
-\r
- This implementation differs from OvmfPkg/Library/LoadLinuxLib. An EFI\r
- stub in the subject kernel is a hard requirement here.\r
-\r
- Copyright (C) 2014, Red Hat, Inc.\r
-\r
- This program and the accompanying materials are licensed and made available\r
- under the terms and conditions of the BSD License which accompanies this\r
- distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
- WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-**/\r
-\r
-#include <Guid/FileInfo.h>\r
-#include <Guid/FileSystemInfo.h>\r
-#include <Guid/FileSystemVolumeLabelInfo.h>\r
-#include <Library/PrintLib.h>\r
-#include <Library/QemuFwCfgLib.h>\r
-#include <Protocol/DevicePath.h>\r
-#include <Protocol/LoadedImage.h>\r
-#include <Protocol/SimpleFileSystem.h>\r
-\r
-#include "IntelBdsPlatform.h"\r
-\r
-//\r
-// Static data that hosts the fw_cfg blobs and serves file requests.\r
-//\r
-typedef enum {\r
- KernelBlobTypeKernel,\r
- KernelBlobTypeInitrd,\r
- KernelBlobTypeCommandLine,\r
- KernelBlobTypeMax\r
-} KERNEL_BLOB_TYPE;\r
-\r
-typedef struct {\r
- FIRMWARE_CONFIG_ITEM CONST SizeKey;\r
- FIRMWARE_CONFIG_ITEM CONST DataKey;\r
- CONST CHAR16 * CONST Name;\r
- UINT32 Size;\r
- UINT8 *Data;\r
-} KERNEL_BLOB;\r
-\r
-STATIC KERNEL_BLOB mKernelBlob[KernelBlobTypeMax] = {\r
- { QemuFwCfgItemKernelSize, QemuFwCfgItemKernelData, L"kernel" },\r
- { QemuFwCfgItemInitrdSize, QemuFwCfgItemInitrdData, L"initrd" },\r
- { QemuFwCfgItemCommandLineSize, QemuFwCfgItemCommandLineData, L"cmdline" }\r
-};\r
-\r
-STATIC UINT64 mTotalBlobBytes;\r
-\r
-//\r
-// Device path for the handle that incorporates our "EFI stub filesystem". The\r
-// GUID is arbitrary and need not be standardized or advertized.\r
-//\r
-#pragma pack(1)\r
-typedef struct {\r
- VENDOR_DEVICE_PATH VenHwNode;\r
- EFI_DEVICE_PATH_PROTOCOL EndNode;\r
-} SINGLE_VENHW_NODE_DEVPATH;\r
-#pragma pack()\r
-\r
-STATIC CONST SINGLE_VENHW_NODE_DEVPATH mFileSystemDevicePath = {\r
- {\r
- { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, { sizeof (VENDOR_DEVICE_PATH) } },\r
- {\r
- 0xb0fae7e7, 0x6b07, 0x49d0,\r
- { 0x9e, 0x5b, 0x3b, 0xde, 0xc8, 0x3b, 0x03, 0x9d }\r
- }\r
- },\r
-\r
- {\r
- END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
- { sizeof (EFI_DEVICE_PATH_PROTOCOL) }\r
- }\r
-};\r
-\r
-//\r
-// The "file in the EFI stub filesystem" abstraction.\r
-//\r
-STATIC EFI_TIME mInitTime;\r
-\r
-#define STUB_FILE_SIG SIGNATURE_64 ('S', 'T', 'U', 'B', 'F', 'I', 'L', 'E')\r
-\r
-typedef struct {\r
- UINT64 Signature; // Carries STUB_FILE_SIG.\r
-\r
- KERNEL_BLOB_TYPE BlobType; // Index into mKernelBlob. KernelBlobTypeMax\r
- // denotes the root directory of the filesystem.\r
-\r
- UINT64 Position; // Byte position for regular files;\r
- // next directory entry to return for the root\r
- // directory.\r
-\r
- EFI_FILE_PROTOCOL File; // Standard protocol interface.\r
-} STUB_FILE;\r
-\r
-#define STUB_FILE_FROM_FILE(FilePointer) \\r
- CR (FilePointer, STUB_FILE, File, STUB_FILE_SIG)\r
-\r
-//\r
-// Tentative definition of the file protocol template. The initializer\r
-// (external definition) will be provided later.\r
-//\r
-STATIC CONST EFI_FILE_PROTOCOL mEfiFileProtocolTemplate;\r
-\r
-\r
-//\r
-// Protocol member functions for File.\r
-//\r
-\r
-/**\r
- Opens a new file relative to the source file's location.\r
-\r
- @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is\r
- the file handle to the source location. This would\r
- typically be an open handle to a directory.\r
-\r
- @param[out] NewHandle A pointer to the location to return the opened handle\r
- for the new file.\r
-\r
- @param[in] FileName The Null-terminated string of the name of the file to\r
- be opened. The file name may contain the following\r
- path modifiers: "\", ".", and "..".\r
-\r
- @param[in] OpenMode The mode to open the file. The only valid\r
- combinations that the file may be opened with are:\r
- Read, Read/Write, or Create/Read/Write.\r
-\r
- @param[in] Attributes Only valid for EFI_FILE_MODE_CREATE, in which case\r
- these are the attribute bits for the newly created\r
- file.\r
-\r
- @retval EFI_SUCCESS The file was opened.\r
- @retval EFI_NOT_FOUND The specified file could not be found on the\r
- device.\r
- @retval EFI_NO_MEDIA The device has no medium.\r
- @retval EFI_MEDIA_CHANGED The device has a different medium in it or the\r
- medium is no longer supported.\r
- @retval EFI_DEVICE_ERROR The device reported an error.\r
- @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
- @retval EFI_WRITE_PROTECTED An attempt was made to create a file, or open a\r
- file for write when the media is\r
- write-protected.\r
- @retval EFI_ACCESS_DENIED The service denied access to the file.\r
- @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the\r
- file.\r
- @retval EFI_VOLUME_FULL The volume is full.\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-StubFileOpen (\r
- IN EFI_FILE_PROTOCOL *This,\r
- OUT EFI_FILE_PROTOCOL **NewHandle,\r
- IN CHAR16 *FileName,\r
- IN UINT64 OpenMode,\r
- IN UINT64 Attributes\r
- )\r
-{\r
- CONST STUB_FILE *StubFile;\r
- UINTN BlobType;\r
- STUB_FILE *NewStubFile;\r
-\r
- //\r
- // We're read-only.\r
- //\r
- switch (OpenMode) {\r
- case EFI_FILE_MODE_READ:\r
- break;\r
-\r
- case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE:\r
- case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE:\r
- return EFI_WRITE_PROTECTED;\r
-\r
- default:\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // Only the root directory supports opening files in it.\r
- //\r
- StubFile = STUB_FILE_FROM_FILE (This);\r
- if (StubFile->BlobType != KernelBlobTypeMax) {\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- //\r
- // Locate the file.\r
- //\r
- for (BlobType = 0; BlobType < KernelBlobTypeMax; ++BlobType) {\r
- if (StrCmp (FileName, mKernelBlob[BlobType].Name) == 0) {\r
- break;\r
- }\r
- }\r
- if (BlobType == KernelBlobTypeMax) {\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- //\r
- // Found it.\r
- //\r
- NewStubFile = AllocatePool (sizeof *NewStubFile);\r
- if (NewStubFile == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- NewStubFile->Signature = STUB_FILE_SIG;\r
- NewStubFile->BlobType = (KERNEL_BLOB_TYPE)BlobType;\r
- NewStubFile->Position = 0;\r
- CopyMem (&NewStubFile->File, &mEfiFileProtocolTemplate,\r
- sizeof mEfiFileProtocolTemplate);\r
- *NewHandle = &NewStubFile->File;\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
- Closes a specified file handle.\r
-\r
- @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the file\r
- handle to close.\r
-\r
- @retval EFI_SUCCESS The file was closed.\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-StubFileClose (\r
- IN EFI_FILE_PROTOCOL *This\r
- )\r
-{\r
- FreePool (STUB_FILE_FROM_FILE (This));\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
- Close and delete the file handle.\r
-\r
- @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the\r
- handle to the file to delete.\r
-\r
- @retval EFI_SUCCESS The file was closed and deleted, and the\r
- handle was closed.\r
- @retval EFI_WARN_DELETE_FAILURE The handle was closed, but the file was not\r
- deleted.\r
-\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-StubFileDelete (\r
- IN EFI_FILE_PROTOCOL *This\r
- )\r
-{\r
- FreePool (STUB_FILE_FROM_FILE (This));\r
- return EFI_WARN_DELETE_FAILURE;\r
-}\r
-\r
-\r
-/**\r
- Helper function that formats an EFI_FILE_INFO structure into the\r
- user-allocated buffer, for any valid KERNEL_BLOB_TYPE value (including\r
- KernelBlobTypeMax, which stands for the root directory).\r
-\r
- The interface follows the EFI_FILE_GET_INFO -- and for directories, the\r
- EFI_FILE_READ -- interfaces.\r
-\r
- @param[in] BlobType The KERNEL_BLOB_TYPE value identifying the fw_cfg\r
- blob backing the STUB_FILE that information is\r
- being requested about. If BlobType equals\r
- KernelBlobTypeMax, then information will be\r
- provided about the root directory of the\r
- filesystem.\r
-\r
- @param[in,out] BufferSize On input, the size of Buffer. On output, the\r
- amount of data returned in Buffer. In both cases,\r
- the size is measured in bytes.\r
-\r
- @param[out] Buffer A pointer to the data buffer to return. The\r
- buffer's type is EFI_FILE_INFO.\r
-\r
- @retval EFI_SUCCESS The information was returned.\r
- @retval EFI_BUFFER_TOO_SMALL BufferSize is too small to store the\r
- EFI_FILE_INFO structure. BufferSize has been\r
- updated with the size needed to complete the\r
- request.\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-ConvertKernelBlobTypeToFileInfo (\r
- IN KERNEL_BLOB_TYPE BlobType,\r
- IN OUT UINTN *BufferSize,\r
- OUT VOID *Buffer\r
- )\r
-{\r
- CONST CHAR16 *Name;\r
- UINT64 FileSize;\r
- UINT64 Attribute;\r
-\r
- UINTN NameSize;\r
- UINTN FileInfoSize;\r
- EFI_FILE_INFO *FileInfo;\r
- UINTN OriginalBufferSize;\r
-\r
- if (BlobType == KernelBlobTypeMax) {\r
- //\r
- // getting file info about the root directory\r
- //\r
- Name = L"\\";\r
- FileSize = KernelBlobTypeMax;\r
- Attribute = EFI_FILE_READ_ONLY | EFI_FILE_DIRECTORY;\r
- } else {\r
- CONST KERNEL_BLOB *Blob;\r
-\r
- Blob = &mKernelBlob[BlobType];\r
- Name = Blob->Name;\r
- FileSize = Blob->Size;\r
- Attribute = EFI_FILE_READ_ONLY;\r
- }\r
-\r
- NameSize = (StrLen(Name) + 1) * 2;\r
- FileInfoSize = OFFSET_OF (EFI_FILE_INFO, FileName) + NameSize;\r
- ASSERT (FileInfoSize >= sizeof *FileInfo);\r
-\r
- OriginalBufferSize = *BufferSize;\r
- *BufferSize = FileInfoSize;\r
- if (OriginalBufferSize < *BufferSize) {\r
- return EFI_BUFFER_TOO_SMALL;\r
- }\r
-\r
- FileInfo = (EFI_FILE_INFO *)Buffer;\r
- FileInfo->Size = FileInfoSize;\r
- FileInfo->FileSize = FileSize;\r
- FileInfo->PhysicalSize = FileSize;\r
- FileInfo->Attribute = Attribute;\r
-\r
- CopyMem (&FileInfo->CreateTime, &mInitTime, sizeof mInitTime);\r
- CopyMem (&FileInfo->LastAccessTime, &mInitTime, sizeof mInitTime);\r
- CopyMem (&FileInfo->ModificationTime, &mInitTime, sizeof mInitTime);\r
- CopyMem (FileInfo->FileName, Name, NameSize);\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
- Reads data from a file, or continues scanning a directory.\r
-\r
- @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that\r
- is the file handle to read data from.\r
-\r
- @param[in,out] BufferSize On input, the size of the Buffer. On output, the\r
- amount of data returned in Buffer. In both cases,\r
- the size is measured in bytes. If the read goes\r
- beyond the end of the file, the read length is\r
- truncated to the end of the file.\r
-\r
- If This is a directory, the function reads the\r
- directory entry at the current position and\r
- returns the entry (as EFI_FILE_INFO) in Buffer. If\r
- there are no more directory entries, the\r
- BufferSize is set to zero on output.\r
-\r
- @param[out] Buffer The buffer into which the data is read.\r
-\r
- @retval EFI_SUCCESS Data was read.\r
- @retval EFI_NO_MEDIA The device has no medium.\r
- @retval EFI_DEVICE_ERROR The device reported an error.\r
- @retval EFI_DEVICE_ERROR An attempt was made to read from a deleted\r
- file.\r
- @retval EFI_DEVICE_ERROR On entry, the current file position is beyond\r
- the end of the file.\r
- @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
- @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to store the\r
- current directory entry as a EFI_FILE_INFO\r
- structure. BufferSize has been updated with the\r
- size needed to complete the request, and the\r
- directory position has not been advanced.\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-StubFileRead (\r
- IN EFI_FILE_PROTOCOL *This,\r
- IN OUT UINTN *BufferSize,\r
- OUT VOID *Buffer\r
- )\r
-{\r
- STUB_FILE *StubFile;\r
- CONST KERNEL_BLOB *Blob;\r
- UINT64 Left;\r
-\r
- StubFile = STUB_FILE_FROM_FILE (This);\r
-\r
- //\r
- // Scanning the root directory?\r
- //\r
- if (StubFile->BlobType == KernelBlobTypeMax) {\r
- EFI_STATUS Status;\r
-\r
- if (StubFile->Position == KernelBlobTypeMax) {\r
- //\r
- // Scanning complete.\r
- //\r
- *BufferSize = 0;\r
- return EFI_SUCCESS;\r
- }\r
-\r
- Status = ConvertKernelBlobTypeToFileInfo (\r
- (KERNEL_BLOB_TYPE)StubFile->Position,\r
- BufferSize,\r
- Buffer);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- ++StubFile->Position;\r
- return EFI_SUCCESS;\r
- }\r
-\r
- //\r
- // Reading a file.\r
- //\r
- Blob = &mKernelBlob[StubFile->BlobType];\r
- if (StubFile->Position > Blob->Size) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- Left = Blob->Size - StubFile->Position;\r
- if (*BufferSize > Left) {\r
- *BufferSize = (UINTN)Left;\r
- }\r
- if (Blob->Data != NULL) {\r
- CopyMem (Buffer, Blob->Data + StubFile->Position, *BufferSize);\r
- }\r
- StubFile->Position += *BufferSize;\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
- Writes data to a file.\r
-\r
- @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that\r
- is the file handle to write data to.\r
-\r
- @param[in,out] BufferSize On input, the size of the Buffer. On output, the\r
- amount of data actually written. In both cases,\r
- the size is measured in bytes.\r
-\r
- @param[in] Buffer The buffer of data to write.\r
-\r
- @retval EFI_SUCCESS Data was written.\r
- @retval EFI_UNSUPPORTED Writes to open directory files are not\r
- supported.\r
- @retval EFI_NO_MEDIA The device has no medium.\r
- @retval EFI_DEVICE_ERROR The device reported an error.\r
- @retval EFI_DEVICE_ERROR An attempt was made to write to a deleted file.\r
- @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
- @retval EFI_WRITE_PROTECTED The file or medium is write-protected.\r
- @retval EFI_ACCESS_DENIED The file was opened read only.\r
- @retval EFI_VOLUME_FULL The volume is full.\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-StubFileWrite (\r
- IN EFI_FILE_PROTOCOL *This,\r
- IN OUT UINTN *BufferSize,\r
- IN VOID *Buffer\r
- )\r
-{\r
- STUB_FILE *StubFile;\r
-\r
- StubFile = STUB_FILE_FROM_FILE (This);\r
- return (StubFile->BlobType == KernelBlobTypeMax) ?\r
- EFI_UNSUPPORTED :\r
- EFI_WRITE_PROTECTED;\r
-}\r
-\r
-\r
-/**\r
- Returns a file's current position.\r
-\r
- @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the\r
- file handle to get the current position on.\r
-\r
- @param[out] Position The address to return the file's current position\r
- value.\r
-\r
- @retval EFI_SUCCESS The position was returned.\r
- @retval EFI_UNSUPPORTED The request is not valid on open directories.\r
- @retval EFI_DEVICE_ERROR An attempt was made to get the position from a\r
- deleted file.\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-StubFileGetPosition (\r
- IN EFI_FILE_PROTOCOL *This,\r
- OUT UINT64 *Position\r
- )\r
-{\r
- STUB_FILE *StubFile;\r
-\r
- StubFile = STUB_FILE_FROM_FILE (This);\r
- if (StubFile->BlobType == KernelBlobTypeMax) {\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- *Position = StubFile->Position;\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
- Sets a file's current position.\r
-\r
- @param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the\r
- file handle to set the requested position on.\r
-\r
- @param[in] Position The byte position from the start of the file to set. For\r
- regular files, MAX_UINT64 means "seek to end". For\r
- directories, zero means "rewind directory scan".\r
-\r
- @retval EFI_SUCCESS The position was set.\r
- @retval EFI_UNSUPPORTED The seek request for nonzero is not valid on open\r
- directories.\r
- @retval EFI_DEVICE_ERROR An attempt was made to set the position of a\r
- deleted file.\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-StubFileSetPosition (\r
- IN EFI_FILE_PROTOCOL *This,\r
- IN UINT64 Position\r
- )\r
-{\r
- STUB_FILE *StubFile;\r
- KERNEL_BLOB *Blob;\r
-\r
- StubFile = STUB_FILE_FROM_FILE (This);\r
-\r
- if (StubFile->BlobType == KernelBlobTypeMax) {\r
- if (Position == 0) {\r
- //\r
- // rewinding a directory scan is allowed\r
- //\r
- StubFile->Position = 0;\r
- return EFI_SUCCESS;\r
- }\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- //\r
- // regular file seek\r
- //\r
- Blob = &mKernelBlob[StubFile->BlobType];\r
- if (Position == MAX_UINT64) {\r
- //\r
- // seek to end\r
- //\r
- StubFile->Position = Blob->Size;\r
- } else {\r
- //\r
- // absolute seek from beginning -- seeking past the end is allowed\r
- //\r
- StubFile->Position = Position;\r
- }\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
- Returns information about a file.\r
-\r
- @param[in] This A pointer to the EFI_FILE_PROTOCOL instance\r
- that is the file handle the requested\r
- information is for.\r
-\r
- @param[in] InformationType The type identifier GUID for the information\r
- being requested. The following information\r
- types are supported, storing the\r
- corresponding structures in Buffer:\r
-\r
- - gEfiFileInfoGuid: EFI_FILE_INFO\r
-\r
- - gEfiFileSystemInfoGuid:\r
- EFI_FILE_SYSTEM_INFO\r
-\r
- - gEfiFileSystemVolumeLabelInfoIdGuid:\r
- EFI_FILE_SYSTEM_VOLUME_LABEL\r
-\r
- @param[in,out] BufferSize On input, the size of Buffer. On output, the\r
- amount of data returned in Buffer. In both\r
- cases, the size is measured in bytes.\r
-\r
- @param[out] Buffer A pointer to the data buffer to return. The\r
- buffer's type is indicated by\r
- InformationType.\r
-\r
- @retval EFI_SUCCESS The information was returned.\r
- @retval EFI_UNSUPPORTED The InformationType is not known.\r
- @retval EFI_NO_MEDIA The device has no medium.\r
- @retval EFI_DEVICE_ERROR The device reported an error.\r
- @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
- @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to store the\r
- information structure requested by\r
- InformationType. BufferSize has been updated\r
- with the size needed to complete the request.\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-StubFileGetInfo (\r
- IN EFI_FILE_PROTOCOL *This,\r
- IN EFI_GUID *InformationType,\r
- IN OUT UINTN *BufferSize,\r
- OUT VOID *Buffer\r
- )\r
-{\r
- CONST STUB_FILE *StubFile;\r
- UINTN OriginalBufferSize;\r
-\r
- StubFile = STUB_FILE_FROM_FILE (This);\r
-\r
- if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {\r
- return ConvertKernelBlobTypeToFileInfo (StubFile->BlobType, BufferSize,\r
- Buffer);\r
- }\r
-\r
- OriginalBufferSize = *BufferSize;\r
-\r
- if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {\r
- EFI_FILE_SYSTEM_INFO *FileSystemInfo;\r
-\r
- *BufferSize = sizeof *FileSystemInfo;\r
- if (OriginalBufferSize < *BufferSize) {\r
- return EFI_BUFFER_TOO_SMALL;\r
- }\r
-\r
- FileSystemInfo = (EFI_FILE_SYSTEM_INFO *)Buffer;\r
- FileSystemInfo->Size = sizeof *FileSystemInfo;\r
- FileSystemInfo->ReadOnly = TRUE;\r
- FileSystemInfo->VolumeSize = mTotalBlobBytes;\r
- FileSystemInfo->FreeSpace = 0;\r
- FileSystemInfo->BlockSize = 1;\r
- FileSystemInfo->VolumeLabel[0] = L'\0';\r
-\r
- return EFI_SUCCESS;\r
- }\r
-\r
- if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {\r
- EFI_FILE_SYSTEM_VOLUME_LABEL *FileSystemVolumeLabel;\r
-\r
- *BufferSize = sizeof *FileSystemVolumeLabel;\r
- if (OriginalBufferSize < *BufferSize) {\r
- return EFI_BUFFER_TOO_SMALL;\r
- }\r
-\r
- FileSystemVolumeLabel = (EFI_FILE_SYSTEM_VOLUME_LABEL *)Buffer;\r
- FileSystemVolumeLabel->VolumeLabel[0] = L'\0';\r
-\r
- return EFI_SUCCESS;\r
- }\r
-\r
- return EFI_UNSUPPORTED;\r
-}\r
-\r
-\r
-/**\r
- Sets information about a file.\r
-\r
- @param[in] File A pointer to the EFI_FILE_PROTOCOL instance that\r
- is the file handle the information is for.\r
-\r
- @param[in] InformationType The type identifier for the information being\r
- set.\r
-\r
- @param[in] BufferSize The size, in bytes, of Buffer.\r
-\r
- @param[in] Buffer A pointer to the data buffer to write. The\r
- buffer's type is indicated by InformationType.\r
-\r
- @retval EFI_SUCCESS The information was set.\r
- @retval EFI_UNSUPPORTED The InformationType is not known.\r
- @retval EFI_NO_MEDIA The device has no medium.\r
- @retval EFI_DEVICE_ERROR The device reported an error.\r
- @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
- @retval EFI_WRITE_PROTECTED InformationType is EFI_FILE_INFO_ID and the\r
- media is read-only.\r
- @retval EFI_WRITE_PROTECTED InformationType is\r
- EFI_FILE_PROTOCOL_SYSTEM_INFO_ID and the media\r
- is read only.\r
- @retval EFI_WRITE_PROTECTED InformationType is\r
- EFI_FILE_SYSTEM_VOLUME_LABEL_ID and the media\r
- is read-only.\r
- @retval EFI_ACCESS_DENIED An attempt is made to change the name of a file\r
- to a file that is already present.\r
- @retval EFI_ACCESS_DENIED An attempt is being made to change the\r
- EFI_FILE_DIRECTORY Attribute.\r
- @retval EFI_ACCESS_DENIED An attempt is being made to change the size of\r
- a directory.\r
- @retval EFI_ACCESS_DENIED InformationType is EFI_FILE_INFO_ID and the\r
- file was opened read-only and an attempt is\r
- being made to modify a field other than\r
- Attribute.\r
- @retval EFI_VOLUME_FULL The volume is full.\r
- @retval EFI_BAD_BUFFER_SIZE BufferSize is smaller than the size of the type\r
- indicated by InformationType.\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-StubFileSetInfo (\r
- IN EFI_FILE_PROTOCOL *This,\r
- IN EFI_GUID *InformationType,\r
- IN UINTN BufferSize,\r
- IN VOID *Buffer\r
- )\r
-{\r
- return EFI_WRITE_PROTECTED;\r
-}\r
-\r
-\r
-/**\r
- Flushes all modified data associated with a file to a device.\r
-\r
- @param [in] This A pointer to the EFI_FILE_PROTOCOL instance that is the\r
- file handle to flush.\r
-\r
- @retval EFI_SUCCESS The data was flushed.\r
- @retval EFI_NO_MEDIA The device has no medium.\r
- @retval EFI_DEVICE_ERROR The device reported an error.\r
- @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
- @retval EFI_WRITE_PROTECTED The file or medium is write-protected.\r
- @retval EFI_ACCESS_DENIED The file was opened read-only.\r
- @retval EFI_VOLUME_FULL The volume is full.\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-StubFileFlush (\r
- IN EFI_FILE_PROTOCOL *This\r
- )\r
-{\r
- return EFI_WRITE_PROTECTED;\r
-}\r
-\r
-//\r
-// External definition of the file protocol template.\r
-//\r
-STATIC CONST EFI_FILE_PROTOCOL mEfiFileProtocolTemplate = {\r
- EFI_FILE_PROTOCOL_REVISION, // revision 1\r
- StubFileOpen,\r
- StubFileClose,\r
- StubFileDelete,\r
- StubFileRead,\r
- StubFileWrite,\r
- StubFileGetPosition,\r
- StubFileSetPosition,\r
- StubFileGetInfo,\r
- StubFileSetInfo,\r
- StubFileFlush,\r
- NULL, // OpenEx, revision 2\r
- NULL, // ReadEx, revision 2\r
- NULL, // WriteEx, revision 2\r
- NULL // FlushEx, revision 2\r
-};\r
-\r
-\r
-//\r
-// Protocol member functions for SimpleFileSystem.\r
-//\r
-\r
-/**\r
- Open the root directory on a volume.\r
-\r
- @param[in] This A pointer to the volume to open the root directory on.\r
-\r
- @param[out] Root A pointer to the location to return the opened file handle\r
- for the root directory in.\r
-\r
- @retval EFI_SUCCESS The device was opened.\r
- @retval EFI_UNSUPPORTED This volume does not support the requested file\r
- system type.\r
- @retval EFI_NO_MEDIA The device has no medium.\r
- @retval EFI_DEVICE_ERROR The device reported an error.\r
- @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
- @retval EFI_ACCESS_DENIED The service denied access to the file.\r
- @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of\r
- resources.\r
- @retval EFI_MEDIA_CHANGED The device has a different medium in it or the\r
- medium is no longer supported. Any existing\r
- file handles for this volume are no longer\r
- valid. To access the files on the new medium,\r
- the volume must be reopened with OpenVolume().\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-StubFileSystemOpenVolume (\r
- IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,\r
- OUT EFI_FILE_PROTOCOL **Root\r
- )\r
-{\r
- STUB_FILE *StubFile;\r
-\r
- StubFile = AllocatePool (sizeof *StubFile);\r
- if (StubFile == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- StubFile->Signature = STUB_FILE_SIG;\r
- StubFile->BlobType = KernelBlobTypeMax;\r
- StubFile->Position = 0;\r
- CopyMem (&StubFile->File, &mEfiFileProtocolTemplate,\r
- sizeof mEfiFileProtocolTemplate);\r
- *Root = &StubFile->File;\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-STATIC CONST EFI_SIMPLE_FILE_SYSTEM_PROTOCOL mFileSystem = {\r
- EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION,\r
- StubFileSystemOpenVolume\r
-};\r
-\r
-\r
-//\r
-// Utility functions.\r
-//\r
-\r
-/**\r
- Populate a blob in mKernelBlob.\r
-\r
- param[in,out] Blob Pointer to the KERNEL_BLOB element in mKernelBlob that is\r
- to be filled from fw_cfg.\r
-\r
- @retval EFI_SUCCESS Blob has been populated. If fw_cfg reported a\r
- size of zero for the blob, then Blob->Data has\r
- been left unchanged.\r
-\r
- @retval EFI_OUT_OF_RESOURCES Failed to allocate memory for Blob->Data.\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-FetchBlob (\r
- IN OUT KERNEL_BLOB *Blob\r
- )\r
-{\r
- UINT32 Left;\r
-\r
- //\r
- // Read blob size.\r
- //\r
- QemuFwCfgSelectItem (Blob->SizeKey);\r
- Blob->Size = QemuFwCfgRead32 ();\r
- if (Blob->Size == 0) {\r
- return EFI_SUCCESS;\r
- }\r
-\r
- //\r
- // Read blob.\r
- //\r
- Blob->Data = AllocatePool (Blob->Size);\r
- if (Blob->Data == NULL) {\r
- DEBUG ((EFI_D_ERROR, "%a: failed to allocate %Ld bytes for \"%s\"\n",\r
- __FUNCTION__, (INT64)Blob->Size, Blob->Name));\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- DEBUG ((EFI_D_INFO, "%a: loading %Ld bytes for \"%s\"\n", __FUNCTION__,\r
- (INT64)Blob->Size, Blob->Name));\r
- QemuFwCfgSelectItem (Blob->DataKey);\r
-\r
- Left = Blob->Size;\r
- do {\r
- UINT32 Chunk;\r
-\r
- Chunk = (Left < SIZE_1MB) ? Left : SIZE_1MB;\r
- QemuFwCfgReadBytes (Chunk, Blob->Data + (Blob->Size - Left));\r
- Left -= Chunk;\r
- DEBUG ((EFI_D_VERBOSE, "%a: %Ld bytes remaining for \"%s\"\n",\r
- __FUNCTION__, (INT64)Left, Blob->Name));\r
- } while (Left > 0);\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
-//\r
-// The entry point of the feature.\r
-//\r
-\r
-/**\r
- Download the kernel, the initial ramdisk, and the kernel command line from\r
- QEMU's fw_cfg. Construct a minimal SimpleFileSystem that contains the two\r
- image files, and load and start the kernel from it.\r
-\r
- The kernel will be instructed via its command line to load the initrd from\r
- the same Simple FileSystem.\r
-\r
- @retval EFI_NOT_FOUND Kernel image was not found.\r
- @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
- @retval EFI_PROTOCOL_ERROR Unterminated kernel command line.\r
-\r
- @return Error codes from any of the underlying\r
- functions. On success, the function doesn't\r
- return.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-TryRunningQemuKernel (\r
- VOID\r
- )\r
-{\r
- UINTN BlobType;\r
- KERNEL_BLOB *CurrentBlob;\r
- KERNEL_BLOB *KernelBlob, *InitrdBlob, *CommandLineBlob;\r
- EFI_STATUS Status;\r
- EFI_HANDLE FileSystemHandle;\r
- EFI_DEVICE_PATH_PROTOCOL *KernelDevicePath;\r
- EFI_HANDLE KernelImageHandle;\r
- EFI_LOADED_IMAGE_PROTOCOL *KernelLoadedImage;\r
-\r
- Status = gRT->GetTime (&mInitTime, NULL /* Capabilities */);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "%a: GetTime(): %r\n", __FUNCTION__, Status));\r
- return Status;\r
- }\r
-\r
- //\r
- // Fetch all blobs.\r
- //\r
- for (BlobType = 0; BlobType < KernelBlobTypeMax; ++BlobType) {\r
- CurrentBlob = &mKernelBlob[BlobType];\r
- Status = FetchBlob (CurrentBlob);\r
- if (EFI_ERROR (Status)) {\r
- goto FreeBlobs;\r
- }\r
- mTotalBlobBytes += CurrentBlob->Size;\r
- }\r
- KernelBlob = &mKernelBlob[KernelBlobTypeKernel];\r
- InitrdBlob = &mKernelBlob[KernelBlobTypeInitrd];\r
- CommandLineBlob = &mKernelBlob[KernelBlobTypeCommandLine];\r
-\r
- if (KernelBlob->Data == NULL) {\r
- Status = EFI_NOT_FOUND;\r
- goto FreeBlobs;\r
- }\r
-\r
- //\r
- // Create a new handle with a single VenHw() node device path protocol on it,\r
- // plus a custom SimpleFileSystem protocol on it.\r
- //\r
- FileSystemHandle = NULL;\r
- Status = gBS->InstallMultipleProtocolInterfaces (&FileSystemHandle,\r
- &gEfiDevicePathProtocolGuid, &mFileSystemDevicePath,\r
- &gEfiSimpleFileSystemProtocolGuid, &mFileSystem,\r
- NULL);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "%a: InstallMultipleProtocolInterfaces(): %r\n",\r
- __FUNCTION__, Status));\r
- goto FreeBlobs;\r
- }\r
-\r
- //\r
- // Create a device path for the kernel image to be loaded from that will call\r
- // back into our file system.\r
- //\r
- KernelDevicePath = FileDevicePath (FileSystemHandle, KernelBlob->Name);\r
- if (KernelDevicePath == NULL) {\r
- DEBUG ((EFI_D_ERROR, "%a: failed to allocate kernel device path\n",\r
- __FUNCTION__));\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto UninstallProtocols;\r
- }\r
-\r
- //\r
- // Load the image. This should call back into our file system.\r
- //\r
- Status = gBS->LoadImage (\r
- FALSE, // BootPolicy: exact match required\r
- gImageHandle, // ParentImageHandle\r
- KernelDevicePath,\r
- NULL, // SourceBuffer\r
- 0, // SourceSize\r
- &KernelImageHandle\r
- );\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "%a: LoadImage(): %r\n", __FUNCTION__, Status));\r
- goto FreeKernelDevicePath;\r
- }\r
-\r
- //\r
- // Construct the kernel command line.\r
- //\r
- Status = gBS->OpenProtocol (\r
- KernelImageHandle,\r
- &gEfiLoadedImageProtocolGuid,\r
- (VOID **)&KernelLoadedImage,\r
- gImageHandle, // AgentHandle\r
- NULL, // ControllerHandle\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- if (CommandLineBlob->Data == NULL) {\r
- KernelLoadedImage->LoadOptionsSize = 0;\r
- } else {\r
- //\r
- // Verify NUL-termination of the command line.\r
- //\r
- if (CommandLineBlob->Data[CommandLineBlob->Size - 1] != '\0') {\r
- DEBUG ((EFI_D_ERROR, "%a: kernel command line is not NUL-terminated\n",\r
- __FUNCTION__));\r
- Status = EFI_PROTOCOL_ERROR;\r
- goto UnloadKernelImage;\r
- }\r
-\r
- //\r
- // Drop the terminating NUL, convert to UTF-16.\r
- //\r
- KernelLoadedImage->LoadOptionsSize = (CommandLineBlob->Size - 1) * 2;\r
- }\r
-\r
- if (InitrdBlob->Data != NULL) {\r
- //\r
- // Append ' initrd=<name>' in UTF-16.\r
- //\r
- KernelLoadedImage->LoadOptionsSize +=\r
- (8 + StrLen(InitrdBlob->Name)) * 2;\r
- }\r
-\r
- if (KernelLoadedImage->LoadOptionsSize == 0) {\r
- KernelLoadedImage->LoadOptions = NULL;\r
- } else {\r
- //\r
- // NUL-terminate in UTF-16.\r
- //\r
- KernelLoadedImage->LoadOptionsSize += 2;\r
-\r
- KernelLoadedImage->LoadOptions = AllocatePool (\r
- KernelLoadedImage->LoadOptionsSize);\r
- if (KernelLoadedImage->LoadOptions == NULL) {\r
- KernelLoadedImage->LoadOptionsSize = 0;\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto UnloadKernelImage;\r
- }\r
-\r
- UnicodeSPrintAsciiFormat (\r
- KernelLoadedImage->LoadOptions,\r
- KernelLoadedImage->LoadOptionsSize,\r
- "%a%a%s",\r
- (CommandLineBlob->Data == NULL) ? "" : (CHAR8 *)CommandLineBlob->Data,\r
- (InitrdBlob->Data == NULL) ? "" : " initrd=",\r
- (InitrdBlob->Data == NULL) ? L"" : InitrdBlob->Name\r
- );\r
- DEBUG ((EFI_D_INFO, "%a: command line: \"%s\"\n", __FUNCTION__,\r
- (CHAR16 *)KernelLoadedImage->LoadOptions));\r
- }\r
-\r
- //\r
- // Signal the EFI_EVENT_GROUP_READY_TO_BOOT event.\r
- //\r
- EfiSignalEventReadyToBoot();\r
-\r
- //\r
- // Start the image.\r
- //\r
- Status = gBS->StartImage (\r
- KernelImageHandle,\r
- NULL, // ExitDataSize\r
- NULL // ExitData\r
- );\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "%a: StartImage(): %r\n", __FUNCTION__, Status));\r
- }\r
-\r
- if (KernelLoadedImage->LoadOptions != NULL) {\r
- FreePool (KernelLoadedImage->LoadOptions);\r
- }\r
- KernelLoadedImage->LoadOptionsSize = 0;\r
-\r
-UnloadKernelImage:\r
- gBS->UnloadImage (KernelImageHandle);\r
-\r
-FreeKernelDevicePath:\r
- FreePool (KernelDevicePath);\r
-\r
-UninstallProtocols:\r
- gBS->UninstallMultipleProtocolInterfaces (FileSystemHandle,\r
- &gEfiSimpleFileSystemProtocolGuid, &mFileSystem,\r
- &gEfiDevicePathProtocolGuid, &mFileSystemDevicePath,\r
- NULL);\r
-\r
-FreeBlobs:\r
- while (BlobType > 0) {\r
- CurrentBlob = &mKernelBlob[--BlobType];\r
- if (CurrentBlob->Data != NULL) {\r
- FreePool (CurrentBlob->Data);\r
- CurrentBlob->Size = 0;\r
- CurrentBlob->Data = NULL;\r
- }\r
- }\r
-\r
- return Status;\r
-}\r