X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=ArmPlatformPkg%2FBds%2FBootOption.c;h=6a5f010abe85467cbcf36a74e8c453c98b2c98e0;hb=a6e97d28aa583e4b7959431cbf8bbd7269d5065d;hp=a8ba23fe739ce0e9ca83bbcc23526ed7c19c8e95;hpb=ea46ebbe6a5a579ff341071a13ae625e15edae64;p=mirror_edk2.git diff --git a/ArmPlatformPkg/Bds/BootOption.c b/ArmPlatformPkg/Bds/BootOption.c index a8ba23fe73..6a5f010abe 100644 --- a/ArmPlatformPkg/Bds/BootOption.c +++ b/ArmPlatformPkg/Bds/BootOption.c @@ -21,27 +21,71 @@ BootOptionStart ( IN BDS_LOAD_OPTION *BootOption ) { - EFI_STATUS Status; - EFI_DEVICE_PATH* FdtDevicePath; - EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *EfiDevicePathFromTextProtocol; + EFI_STATUS Status; + EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL* EfiDevicePathFromTextProtocol; + UINT32 LoaderType; + ARM_BDS_LOADER_OPTIONAL_DATA* OptionalData; + ARM_BDS_LINUX_ARGUMENTS* LinuxArguments; + EFI_DEVICE_PATH_PROTOCOL* FdtDevicePath; + EFI_DEVICE_PATH_PROTOCOL* DefaultFdtDevicePath; + UINTN FdtDevicePathSize; + UINTN CmdLineSize; + UINTN InitrdSize; + EFI_DEVICE_PATH* Initrd; + + if (IS_ARM_BDS_BOOTENTRY (BootOption)) { + Status = EFI_UNSUPPORTED; + OptionalData = BootOption->OptionalData; + LoaderType = ReadUnaligned32 ((CONST UINT32*)&OptionalData->Header.LoaderType); + + if (LoaderType == BDS_LOADER_EFI_APPLICATION) { + // Need to connect every drivers to ensure no dependencies are missing for the application + BdsConnectAllDrivers(); + + Status = BdsStartEfiApplication (mImageHandle, BootOption->FilePathList, 0, NULL); + } else if (LoaderType == BDS_LOADER_KERNEL_LINUX_ATAG) { + LinuxArguments = &(OptionalData->Arguments.LinuxArguments); + CmdLineSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->CmdLineSize); + InitrdSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->InitrdSize); + + if (InitrdSize > 0) { + Initrd = GetAlignedDevicePath ((EFI_DEVICE_PATH*)((UINTN)(LinuxArguments + 1) + CmdLineSize)); + } else { + Initrd = NULL; + } + + Status = BdsBootLinux (BootOption->FilePathList, + Initrd, // Initrd + (CHAR8*)(LinuxArguments + 1), // CmdLine + NULL); + } else if (LoaderType == BDS_LOADER_KERNEL_LINUX_FDT) { + LinuxArguments = &(OptionalData->Arguments.LinuxArguments); + CmdLineSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->CmdLineSize); + InitrdSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->InitrdSize); + + if (InitrdSize > 0) { + Initrd = GetAlignedDevicePath ((EFI_DEVICE_PATH*)((UINTN)(LinuxArguments + 1) + CmdLineSize)); + } else { + Initrd = NULL; + } - Status = EFI_UNSUPPORTED; + // Get the default FDT device path + Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol); + ASSERT_EFI_ERROR(Status); + DefaultFdtDevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath ((CHAR16*)PcdGetPtr(PcdFdtDevicePath)); - if (BootOption->OptionalData->LoaderType == BDS_LOADER_EFI_APPLICATION) { - // Need to connect every drivers to ensure no dependencies are missing for the application - BdsConnectAllDrivers(); + // Get the FDT device path + FdtDevicePathSize = GetDevicePathSize (DefaultFdtDevicePath); + Status = GetEnvironmentVariable ((CHAR16 *)L"FDT", DefaultFdtDevicePath, &FdtDevicePathSize, (VOID **)&FdtDevicePath); + ASSERT_EFI_ERROR(Status); + Status = BdsBootLinux (BootOption->FilePathList, + Initrd, // Initrd + (CHAR8*)(LinuxArguments + 1), + FdtDevicePath); + } + } else { Status = BdsStartEfiApplication (mImageHandle, BootOption->FilePathList); - } else if (BootOption->OptionalData->LoaderType == BDS_LOADER_KERNEL_LINUX_ATAG) { - Status = BdsBootLinux (BootOption->FilePathList, BootOption->OptionalData->Arguments, NULL); - } else if (BootOption->OptionalData->LoaderType == BDS_LOADER_KERNEL_LINUX_FDT) { - // Convert the FDT path into a Device Path - Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol); - ASSERT_EFI_ERROR(Status); - FdtDevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath ((CHAR16*)PcdGetPtr(PcdFdtDevicePath)); - - Status = BdsBootLinux (BootOption->FilePathList, BootOption->OptionalData->Arguments, FdtDevicePath); - FreePool(FdtDevicePath); } return Status; @@ -119,11 +163,12 @@ BootOptionList ( IN OUT LIST_ENTRY *BootOptionList ) { - EFI_STATUS Status; - UINTN Index; - UINT16 *BootOrder; - UINTN BootOrderSize; - BDS_LOAD_OPTION *BdsLoadOption; + EFI_STATUS Status; + UINTN Index; + UINT16* BootOrder; + UINTN BootOrderSize; + BDS_LOAD_OPTION* BdsLoadOption; + BDS_LOAD_OPTION_ENTRY* BdsLoadOptionEntry; InitializeListHead (BootOptionList); @@ -136,7 +181,9 @@ BootOptionList ( for (Index = 0; Index < BootOrderSize / sizeof (UINT16); Index++) { Status = BootOptionFromLoadOptionVariable (BootOrder[Index],&BdsLoadOption); if (!EFI_ERROR(Status)) { - InsertTailList (BootOptionList,&BdsLoadOption->Link); + BdsLoadOptionEntry = (BDS_LOAD_OPTION_ENTRY*)AllocatePool(sizeof(BDS_LOAD_OPTION_ENTRY)); + BdsLoadOptionEntry->BdsLoadOption = BdsLoadOption; + InsertTailList (BootOptionList,&BdsLoadOptionEntry->Link); } } @@ -178,41 +225,38 @@ BootOptionAllocateBootIndex ( STATIC EFI_STATUS BootOptionSetFields ( - IN BDS_LOAD_OPTION *BootOption, - IN UINT32 Attributes, - IN CHAR16* BootDescription, - IN EFI_DEVICE_PATH_PROTOCOL* DevicePath, - IN BDS_LOADER_TYPE BootType, - IN CHAR8* BootArguments + IN BDS_LOAD_OPTION* BootOption, + IN UINT32 Attributes, + IN CHAR16* BootDescription, + IN EFI_DEVICE_PATH_PROTOCOL* DevicePath, + IN ARM_BDS_LOADER_TYPE BootType, + IN ARM_BDS_LOADER_ARGUMENTS* BootArguments ) { - EFI_LOAD_OPTION EfiLoadOption; - UINTN EfiLoadOptionSize; - UINTN BootDescriptionSize; - UINTN BootOptionalDataSize; - UINT16 FilePathListLength; - EFI_DEVICE_PATH_PROTOCOL* DevicePathNode; - UINTN NodeLength; - UINT8* EfiLoadOptionPtr; + EFI_LOAD_OPTION EfiLoadOption; + UINTN EfiLoadOptionSize; + UINTN BootDescriptionSize; + UINTN BootOptionalDataSize; + UINT16 FilePathListLength; + UINT8* EfiLoadOptionPtr; + UINT8* InitrdPathListPtr; + UINTN OptionalDataSize; + ARM_BDS_LINUX_ARGUMENTS* DestLinuxArguments; + ARM_BDS_LINUX_ARGUMENTS* SrcLinuxArguments; // If we are overwriting an existent Boot Option then we have to free previously allocated memory if (BootOption->LoadOption) { FreePool(BootOption->LoadOption); } - BootDescriptionSize = StrSize(BootDescription); - BootOptionalDataSize = sizeof(BDS_LOADER_OPTIONAL_DATA) + - (BootArguments == NULL ? 0 : AsciiStrSize(BootArguments)); + BootDescriptionSize = StrSize (BootDescription); + BootOptionalDataSize = sizeof(ARM_BDS_LOADER_OPTIONAL_DATA_HEADER); + if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_FDT)) { + BootOptionalDataSize += sizeof(ARM_BDS_LINUX_ARGUMENTS) + BootArguments->LinuxArguments.CmdLineSize + BootArguments->LinuxArguments.InitrdSize; + } // Compute the size of the FilePath list - FilePathListLength = 0; - DevicePathNode = DevicePath; - while (!IsDevicePathEndType (DevicePathNode)) { - FilePathListLength += DevicePathNodeLength (DevicePathNode); - DevicePathNode = NextDevicePathNode (DevicePathNode); - } - // Add the length of the DevicePath EndType - FilePathListLength += DevicePathNodeLength (DevicePathNode); + FilePathListLength = GetUnalignedDevicePathSize (DevicePath); // Allocate the memory for the EFI Load Option EfiLoadOptionSize = sizeof(UINT32) + sizeof(UINT16) + BootDescriptionSize + FilePathListLength + BootOptionalDataSize; @@ -240,26 +284,43 @@ BootOptionSetFields ( // File path fields BootOption->FilePathList = (EFI_DEVICE_PATH_PROTOCOL*)EfiLoadOptionPtr; - DevicePathNode = DevicePath; - while (!IsDevicePathEndType (DevicePathNode)) { - NodeLength = DevicePathNodeLength(DevicePathNode); - CopyMem (EfiLoadOptionPtr, DevicePathNode, NodeLength); - EfiLoadOptionPtr += NodeLength; - DevicePathNode = NextDevicePathNode (DevicePathNode); - } - - // Set the End Device Path Type - SetDevicePathEndNode (EfiLoadOptionPtr); - EfiLoadOptionPtr = (UINT8 *)EfiLoadOptionPtr + sizeof(EFI_DEVICE_PATH); + CopyMem (EfiLoadOptionPtr, DevicePath, FilePathListLength); + EfiLoadOptionPtr += FilePathListLength; // Optional Data fields, Do unaligned writes - WriteUnaligned32 ((UINT32 *)EfiLoadOptionPtr, BootType); + BootOption->OptionalData = EfiLoadOptionPtr; + WriteUnaligned32 ((UINT32 *)EfiLoadOptionPtr, ARM_BDS_OPTIONAL_DATA_SIGNATURE); + WriteUnaligned32 ((UINT32 *)(EfiLoadOptionPtr + 4), BootType); + + OptionalDataSize = sizeof(ARM_BDS_LOADER_OPTIONAL_DATA_HEADER); + + if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_FDT)) { + SrcLinuxArguments = &(BootArguments->LinuxArguments); + DestLinuxArguments = &((ARM_BDS_LOADER_OPTIONAL_DATA*)EfiLoadOptionPtr)->Arguments.LinuxArguments; + + WriteUnaligned16 ((UINT16 *)&(DestLinuxArguments->CmdLineSize), SrcLinuxArguments->CmdLineSize); + WriteUnaligned16 ((UINT16 *)&(DestLinuxArguments->InitrdSize), SrcLinuxArguments->InitrdSize); + OptionalDataSize += sizeof (ARM_BDS_LINUX_ARGUMENTS); + + if (SrcLinuxArguments->CmdLineSize > 0) { + CopyMem ((VOID*)(DestLinuxArguments + 1), (VOID*)(SrcLinuxArguments + 1), SrcLinuxArguments->CmdLineSize); + OptionalDataSize += SrcLinuxArguments->CmdLineSize; + } - CopyMem (&((BDS_LOADER_OPTIONAL_DATA*)EfiLoadOptionPtr)->Arguments, BootArguments, AsciiStrSize(BootArguments)); - BootOption->OptionalData = (BDS_LOADER_OPTIONAL_DATA *)EfiLoadOptionPtr; + if (SrcLinuxArguments->InitrdSize > 0) { + InitrdPathListPtr = (UINT8*)((UINTN)(DestLinuxArguments + 1) + SrcLinuxArguments->CmdLineSize); + CopyMem (InitrdPathListPtr, (VOID*)((UINTN)(SrcLinuxArguments + 1) + SrcLinuxArguments->CmdLineSize), SrcLinuxArguments->InitrdSize); + } + } + BootOption->OptionalDataSize = OptionalDataSize; + + // If this function is called at the creation of the Boot Device entry (not at the update) the + // BootOption->LoadOptionSize must be zero then we get a new BootIndex for this entry + if (BootOption->LoadOptionSize == 0) { + BootOption->LoadOptionIndex = BootOptionAllocateBootIndex (); + } // Fill the EFI Load option fields - BootOption->LoadOptionIndex = BootOptionAllocateBootIndex(); BootOption->LoadOption = EfiLoadOption; BootOption->LoadOptionSize = EfiLoadOptionSize; @@ -268,26 +329,29 @@ BootOptionSetFields ( EFI_STATUS BootOptionCreate ( - IN UINT32 Attributes, - IN CHAR16* BootDescription, + IN UINT32 Attributes, + IN CHAR16* BootDescription, IN EFI_DEVICE_PATH_PROTOCOL* DevicePath, - IN BDS_LOADER_TYPE BootType, - IN CHAR8* BootArguments, - OUT BDS_LOAD_OPTION **BdsLoadOption + IN ARM_BDS_LOADER_TYPE BootType, + IN ARM_BDS_LOADER_ARGUMENTS* BootArguments, + OUT BDS_LOAD_OPTION** BdsLoadOption ) { - EFI_STATUS Status; - BDS_LOAD_OPTION *BootOption; - CHAR16 BootVariableName[9]; - UINT16 *BootOrder; - UINTN BootOrderSize; + EFI_STATUS Status; + BDS_LOAD_OPTION_ENTRY* BootOptionEntry; + BDS_LOAD_OPTION* BootOption; + CHAR16 BootVariableName[9]; + UINT16* BootOrder; + UINTN BootOrderSize; // // Allocate and fill the memory for the BDS Load Option structure // - BootOption = (BDS_LOAD_OPTION*)AllocateZeroPool(sizeof(BDS_LOAD_OPTION)); + BootOptionEntry = (BDS_LOAD_OPTION_ENTRY*)AllocatePool (sizeof (BDS_LOAD_OPTION_ENTRY)); + InitializeListHead (&BootOptionEntry->Link); + BootOptionEntry->BdsLoadOption = (BDS_LOAD_OPTION*)AllocateZeroPool (sizeof(BDS_LOAD_OPTION)); - InitializeListHead (&BootOption->Link); + BootOption = BootOptionEntry->BdsLoadOption; BootOptionSetFields (BootOption, Attributes, BootDescription, DevicePath, BootType, BootArguments); // @@ -332,29 +396,29 @@ BootOptionCreate ( EFI_STATUS BootOptionUpdate ( - IN BDS_LOAD_OPTION *BdsLoadOption, - IN UINT32 Attributes, - IN CHAR16* BootDescription, + IN BDS_LOAD_OPTION* BdsLoadOption, + IN UINT32 Attributes, + IN CHAR16* BootDescription, IN EFI_DEVICE_PATH_PROTOCOL* DevicePath, - IN BDS_LOADER_TYPE BootType, - IN CHAR8* BootArguments + IN ARM_BDS_LOADER_TYPE BootType, + IN ARM_BDS_LOADER_ARGUMENTS* BootArguments ) { EFI_STATUS Status; - BDS_LOAD_OPTION *BootOption; CHAR16 BootVariableName[9]; // Update the BDS Load Option structure BootOptionSetFields (BdsLoadOption, Attributes, BootDescription, DevicePath, BootType, BootArguments); // Update the related environment variables - UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", BootOption->LoadOptionIndex); + UnicodeSPrint (BootVariableName, 9 * sizeof(CHAR16), L"Boot%04X", BdsLoadOption->LoadOptionIndex); + Status = gRT->SetVariable ( BootVariableName, &gEfiGlobalVariableGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, - BootOption->LoadOptionSize, - BootOption->LoadOption + BdsLoadOption->LoadOptionSize, + BdsLoadOption->LoadOption ); return Status; @@ -365,17 +429,11 @@ BootOptionDelete ( IN BDS_LOAD_OPTION *BootOption ) { - UINTN Index; - UINTN BootOrderSize; - UINT16* BootOrder; - UINTN BootOrderCount; - EFI_STATUS Status; - - // If the Boot Optiono was attached to a list remove it - if (!IsListEmpty (&BootOption->Link)) { - // Remove the entry from the list - RemoveEntryList (&BootOption->Link); - } + UINTN Index; + UINTN BootOrderSize; + UINT16* BootOrder; + UINTN BootOrderCount; + EFI_STATUS Status; // Remove the entry from the BootOrder environment variable Status = GetEnvironmentVariable (L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder);