From 40d0673c2e3db10e47fd0742bf484c3d0aea2efe Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 15 Nov 2017 16:20:55 +0000 Subject: Platform/ARM: import BootMonFs and ArmShellCmdRunAxf from EDK2 BootMonFs and ArmShellCmdRunAxf are only used on development boards manufactured by ARM itself, so let's keep it under Platform/ARM where it belongs. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Ard Biesheuvel Reviewed-by: Leif Lindholm --- .../ARM/Drivers/BootMonFs/BootMonFsEntryPoint.c | 529 +++++++++++++++++++++ 1 file changed, 529 insertions(+) create mode 100644 Platform/ARM/Drivers/BootMonFs/BootMonFsEntryPoint.c (limited to 'Platform/ARM/Drivers/BootMonFs/BootMonFsEntryPoint.c') diff --git a/Platform/ARM/Drivers/BootMonFs/BootMonFsEntryPoint.c b/Platform/ARM/Drivers/BootMonFs/BootMonFsEntryPoint.c new file mode 100644 index 0000000000..a1150856f6 --- /dev/null +++ b/Platform/ARM/Drivers/BootMonFs/BootMonFsEntryPoint.c @@ -0,0 +1,529 @@ +/** @file +* +* Copyright (c) 2012-2014, ARM Limited. All rights reserved. +* +* This program and the accompanying materials +* are licensed and made available under the terms and conditions of the BSD License +* which accompanies this distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* +**/ + +#include +#include +#include +#include +#include + +#include +#include + +#include "BootMonFsInternal.h" + +EFI_DEVICE_PATH* mBootMonFsSupportedDevicePaths; +LIST_ENTRY mInstances; + +EFI_FILE_PROTOCOL mBootMonFsRootTemplate = { + EFI_FILE_PROTOCOL_REVISION, + BootMonFsOpenFile, + BootMonFsCloseFile, + BootMonFsDeleteFail, + BootMonFsReadDirectory, + BootMonFsWriteFile, + BootMonFsGetPositionUnsupported, // UEFI Spec: GetPosition not valid on dirs + BootMonFsSetDirPosition, + BootMonFsGetInfo, + BootMonFsSetInfo, + BootMonFsFlushDirectory +}; + +EFI_FILE_PROTOCOL mBootMonFsFileTemplate = { + EFI_FILE_PROTOCOL_REVISION, + BootMonFsOpenFile, + BootMonFsCloseFile, + BootMonFsDelete, + BootMonFsReadFile, + BootMonFsWriteFile, + BootMonFsGetPosition, + BootMonFsSetPosition, + BootMonFsGetInfo, + BootMonFsSetInfo, + BootMonFsFlushFile +}; + +/** + Search for a file given its name coded in Ascii. + + When searching through the files of the volume, if a file is currently not + open, its name was written on the media and is kept in RAM in the + "HwDescription.Footer.Filename[]" field of the file's description. + + If a file is currently open, its name might not have been written on the + media yet, and as the "HwDescription" is a mirror in RAM of what is on the + media the "HwDescription.Footer.Filename[]" might be outdated. In that case, + the up to date name of the file is stored in the "Info" field of the file's + description. + + @param[in] Instance Pointer to the description of the volume in which + the file has to be search for. + @param[in] AsciiFileName Name of the file. + + @param[out] File Pointer to the description of the file if the + file was found. + + @retval EFI_SUCCESS The file was found. + @retval EFI_NOT_FOUND The file was not found. + +**/ +EFI_STATUS +BootMonGetFileFromAsciiFileName ( + IN BOOTMON_FS_INSTANCE *Instance, + IN CHAR8* AsciiFileName, + OUT BOOTMON_FS_FILE **File + ) +{ + LIST_ENTRY *Entry; + BOOTMON_FS_FILE *FileEntry; + CHAR8 OpenFileAsciiFileName[MAX_NAME_LENGTH]; + CHAR8 *AsciiFileNameToCompare; + + // Go through all the files in the list and return the file handle + for (Entry = GetFirstNode (&Instance->RootFile->Link); + !IsNull (&Instance->RootFile->Link, Entry); + Entry = GetNextNode (&Instance->RootFile->Link, Entry) + ) + { + FileEntry = BOOTMON_FS_FILE_FROM_LINK_THIS (Entry); + if (FileEntry->Info != NULL) { + UnicodeStrToAsciiStrS (FileEntry->Info->FileName, OpenFileAsciiFileName, + MAX_NAME_LENGTH); + AsciiFileNameToCompare = OpenFileAsciiFileName; + } else { + AsciiFileNameToCompare = FileEntry->HwDescription.Footer.Filename; + } + + if (AsciiStrCmp (AsciiFileNameToCompare, AsciiFileName) == 0) { + *File = FileEntry; + return EFI_SUCCESS; + } + } + return EFI_NOT_FOUND; +} + +EFI_STATUS +BootMonGetFileFromPosition ( + IN BOOTMON_FS_INSTANCE *Instance, + IN UINTN Position, + OUT BOOTMON_FS_FILE **File + ) +{ + LIST_ENTRY *Entry; + BOOTMON_FS_FILE *FileEntry; + + // Go through all the files in the list and return the file handle + for (Entry = GetFirstNode (&Instance->RootFile->Link); + !IsNull (&Instance->RootFile->Link, Entry) && (&Instance->RootFile->Link != Entry); + Entry = GetNextNode (&Instance->RootFile->Link, Entry) + ) + { + if (Position == 0) { + FileEntry = BOOTMON_FS_FILE_FROM_LINK_THIS (Entry); + *File = FileEntry; + return EFI_SUCCESS; + } + Position--; + } + return EFI_NOT_FOUND; +} + +EFI_STATUS +BootMonFsCreateFile ( + IN BOOTMON_FS_INSTANCE *Instance, + OUT BOOTMON_FS_FILE **File + ) +{ + BOOTMON_FS_FILE *NewFile; + + NewFile = (BOOTMON_FS_FILE*)AllocateZeroPool (sizeof (BOOTMON_FS_FILE)); + if (NewFile == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + NewFile->Signature = BOOTMON_FS_FILE_SIGNATURE; + InitializeListHead (&NewFile->Link); + InitializeListHead (&NewFile->RegionToFlushLink); + NewFile->Instance = Instance; + + // If the created file is the root file then create a directory EFI_FILE_PROTOCOL + if (Instance->RootFile == *File) { + CopyMem (&NewFile->File, &mBootMonFsRootTemplate, sizeof (mBootMonFsRootTemplate)); + } else { + CopyMem (&NewFile->File, &mBootMonFsFileTemplate, sizeof (mBootMonFsFileTemplate)); + } + *File = NewFile; + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +SupportedDevicePathsInit ( + VOID + ) +{ + EFI_STATUS Status; + CHAR16* DevicePathListStr; + CHAR16* DevicePathStr; + CHAR16* NextDevicePathStr; + EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *EfiDevicePathFromTextProtocol; + EFI_DEVICE_PATH_PROTOCOL *Instance; + + Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol); + ASSERT_EFI_ERROR (Status); + + // Initialize Variable + DevicePathListStr = (CHAR16*)PcdGetPtr (PcdBootMonFsSupportedDevicePaths); + mBootMonFsSupportedDevicePaths = NULL; + + // Extract the Device Path instances from the multi-device path string + while ((DevicePathListStr != NULL) && (DevicePathListStr[0] != L'\0')) { + NextDevicePathStr = StrStr (DevicePathListStr, L";"); + if (NextDevicePathStr == NULL) { + DevicePathStr = DevicePathListStr; + DevicePathListStr = NULL; + } else { + DevicePathStr = (CHAR16*)AllocateCopyPool ((NextDevicePathStr - DevicePathListStr + 1) * sizeof (CHAR16), DevicePathListStr); + if (DevicePathStr == NULL) { + return EFI_OUT_OF_RESOURCES; + } + *(DevicePathStr + (NextDevicePathStr - DevicePathListStr)) = L'\0'; + DevicePathListStr = NextDevicePathStr; + if (DevicePathListStr[0] == L';') { + DevicePathListStr++; + } + } + + Instance = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath (DevicePathStr); + ASSERT (Instance != NULL); + mBootMonFsSupportedDevicePaths = AppendDevicePathInstance (mBootMonFsSupportedDevicePaths, Instance); + + if (NextDevicePathStr != NULL) { + FreePool (DevicePathStr); + } + FreePool (Instance); + } + + if (mBootMonFsSupportedDevicePaths == NULL) { + return EFI_UNSUPPORTED; + } else { + return EFI_SUCCESS; + } +} + +EFI_STATUS +EFIAPI +BootMonFsDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL + ) +{ + EFI_DISK_IO_PROTOCOL *DiskIo; + EFI_DEVICE_PATH_PROTOCOL *DevicePathProtocol; + EFI_DEVICE_PATH_PROTOCOL *SupportedDevicePath; + EFI_DEVICE_PATH_PROTOCOL *SupportedDevicePaths; + EFI_STATUS Status; + UINTN Size1; + UINTN Size2; + + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiDiskIoProtocolGuid, + (VOID **) &DiskIo, + gImageHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Close the I/O Abstraction(s) used to perform the supported test + // + gBS->CloseProtocol ( + ControllerHandle, + &gEfiDiskIoProtocolGuid, + gImageHandle, + ControllerHandle + ); + + // Check that BlockIo protocol instance exists + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiBlockIoProtocolGuid, + NULL, + gImageHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // Check if a DevicePath is attached to the handle + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiDevicePathProtocolGuid, + (VOID **)&DevicePathProtocol, + gImageHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // Check if the Device Path is the one which contains the Boot Monitor File System + Size1 = GetDevicePathSize (DevicePathProtocol); + + // Go through the list of Device Path Instances + Status = EFI_UNSUPPORTED; + SupportedDevicePaths = mBootMonFsSupportedDevicePaths; + while (SupportedDevicePaths != NULL) { + SupportedDevicePath = GetNextDevicePathInstance (&SupportedDevicePaths, &Size2); + + if ((Size1 == Size2) && (CompareMem (DevicePathProtocol, SupportedDevicePath, Size1) == 0)) { + // The Device Path is supported + Status = EFI_SUCCESS; + break; + } + } + + gBS->CloseProtocol (ControllerHandle, &gEfiDevicePathProtocolGuid, gImageHandle, ControllerHandle); + return Status; +} + +EFI_STATUS +EFIAPI +BootMonFsDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL + ) +{ + BOOTMON_FS_INSTANCE *Instance; + EFI_STATUS Status; + UINTN VolumeNameSize; + EFI_FILE_INFO *Info; + + Instance = AllocateZeroPool (sizeof (BOOTMON_FS_INSTANCE)); + if (Instance == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // Initialize the BlockIo of the Instance + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiBlockIoProtocolGuid, + (VOID **)&(Instance->BlockIo), + gImageHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + goto Error; + } + + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiDiskIoProtocolGuid, + (VOID **)&(Instance->DiskIo), + gImageHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + goto Error; + } + + // + // Initialize the attributes of the Instance + // + Instance->Signature = BOOTMON_FS_SIGNATURE; + Instance->ControllerHandle = ControllerHandle; + Instance->Media = Instance->BlockIo->Media; + Instance->Binding = DriverBinding; + + // Initialize the Simple File System Protocol + Instance->Fs.Revision = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION; + Instance->Fs.OpenVolume = OpenBootMonFsOpenVolume; + + // Volume name + L' ' + '2' digit number + VolumeNameSize = StrSize (BOOTMON_FS_VOLUME_LABEL) + (3 * sizeof (CHAR16)); + + // Initialize FileSystem Information + Instance->FsInfo.Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + VolumeNameSize; + Instance->FsInfo.BlockSize = Instance->Media->BlockSize; + Instance->FsInfo.ReadOnly = FALSE; + Instance->FsInfo.VolumeSize = + Instance->Media->BlockSize * (Instance->Media->LastBlock - Instance->Media->LowestAlignedLba); + CopyMem (Instance->FsInfo.VolumeLabel, BOOTMON_FS_VOLUME_LABEL, StrSize (BOOTMON_FS_VOLUME_LABEL)); + + // Initialize the root file + Status = BootMonFsCreateFile (Instance, &Instance->RootFile); + if (EFI_ERROR (Status)) { + goto Error; + } + + Info = AllocateZeroPool (sizeof (EFI_FILE_INFO)); + if (Info == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Error; + } + Instance->RootFile->Info = Info; + + // Initialize the DevicePath of the Instance + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiDevicePathProtocolGuid, + (VOID **)&(Instance->DevicePath), + gImageHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + goto Error; + } + + // + // Install the Simple File System Protocol + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &ControllerHandle, + &gEfiSimpleFileSystemProtocolGuid, &Instance->Fs, + NULL + ); + if (EFI_ERROR (Status)) { + goto Error; + } + + InsertTailList (&mInstances, &Instance->Link); + + return EFI_SUCCESS; + +Error: + + if (Instance->RootFile != NULL) { + if (Instance->RootFile->Info != NULL) { + FreePool (Instance->RootFile->Info); + } + FreePool (Instance->RootFile); + } + FreePool (Instance); + + return Status; +} + + +EFI_STATUS +EFIAPI +BootMonFsDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer OPTIONAL + ) +{ + BOOTMON_FS_INSTANCE *Instance; + LIST_ENTRY *Link; + EFI_STATUS Status; + BOOLEAN InstanceFound; + + // Find instance from ControllerHandle. + Instance = NULL; + InstanceFound = FALSE; + // For each instance in mInstances: + for (Link = GetFirstNode (&mInstances); !IsNull (&mInstances, Link); Link = GetNextNode (&mInstances, Link)) { + Instance = BOOTMON_FS_FROM_LINK (Link); + + if (Instance->ControllerHandle == ControllerHandle) { + InstanceFound = TRUE; + break; + } + } + ASSERT (InstanceFound == TRUE); + + gBS->CloseProtocol ( + ControllerHandle, + &gEfiDevicePathProtocolGuid, + DriverBinding->ImageHandle, + ControllerHandle); + + gBS->CloseProtocol ( + ControllerHandle, + &gEfiDiskIoProtocolGuid, + DriverBinding->ImageHandle, + ControllerHandle); + + gBS->CloseProtocol ( + ControllerHandle, + &gEfiBlockIoProtocolGuid, + DriverBinding->ImageHandle, + ControllerHandle); + + Status = gBS->UninstallMultipleProtocolInterfaces ( + &ControllerHandle, + &gEfiSimpleFileSystemProtocolGuid, &Instance->Fs, + NULL); + + FreePool (Instance->RootFile->Info); + FreePool (Instance->RootFile); + FreePool (Instance); + + return Status; +} + +// +// Simple Network Protocol Driver Global Variables +// +EFI_DRIVER_BINDING_PROTOCOL mBootMonFsDriverBinding = { + BootMonFsDriverSupported, + BootMonFsDriverStart, + BootMonFsDriverStop, + 0xa, + NULL, + NULL +}; + +EFI_STATUS +EFIAPI +BootMonFsEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + InitializeListHead (&mInstances); + + // Initialize the list of Device Paths that could support BootMonFs + Status = SupportedDevicePathsInit (); + if (!EFI_ERROR (Status)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &ImageHandle, + &gEfiDriverBindingProtocolGuid, &mBootMonFsDriverBinding, + NULL + ); + ASSERT_EFI_ERROR (Status); + } else { + DEBUG((EFI_D_ERROR,"Warning: No Device Paths supporting BootMonFs have been defined in the PCD.\n")); + } + + return Status; +} -- cgit v1.2.3