EFI_STATUS BootMenuAddBootOption ( IN LIST_ENTRY *BootOptionsList ) { EFI_STATUS Status; BDS_SUPPORTED_DEVICE* SupportedBootDevice; ARM_BDS_LOADER_ARGUMENTS* BootArguments; CHAR16 BootDescription[BOOT_DEVICE_DESCRIPTION_MAX]; CHAR8 AsciiCmdLine[BOOT_DEVICE_OPTION_MAX]; CHAR16 CmdLine[BOOT_DEVICE_OPTION_MAX]; UINT32 Attributes; ARM_BDS_LOADER_TYPE BootType; BDS_LOAD_OPTION_ENTRY *BdsLoadOptionEntry; EFI_DEVICE_PATH *DevicePath; EFI_DEVICE_PATH_PROTOCOL *DevicePathNodes; EFI_DEVICE_PATH_PROTOCOL *InitrdPathNodes; EFI_DEVICE_PATH_PROTOCOL *InitrdPath; UINTN CmdLineSize; BOOLEAN InitrdSupport; UINTN InitrdSize; UINT8* OptionalData; UINTN OptionalDataSize; Attributes = 0; SupportedBootDevice = NULL; // List the Boot Devices supported Status = SelectBootDevice (&SupportedBootDevice); if (EFI_ERROR(Status)) { Status = EFI_ABORTED; goto EXIT; } // Create the specific device path node Status = SupportedBootDevice->Support->CreateDevicePathNode (L"EFI Application or the kernel", &DevicePathNodes); if (EFI_ERROR(Status)) { Status = EFI_ABORTED; goto EXIT; } // Append the Device Path to the selected device path DevicePath = AppendDevicePath (SupportedBootDevice->DevicePathProtocol, (CONST EFI_DEVICE_PATH_PROTOCOL *)DevicePathNodes); if (DevicePath == NULL) { Status = EFI_OUT_OF_RESOURCES; goto EXIT; } if (SupportedBootDevice->Support->RequestBootType) { Status = BootDeviceGetType (DevicePath, &BootType, &Attributes); if (EFI_ERROR(Status)) { Status = EFI_ABORTED; goto EXIT; } } else { BootType = BDS_LOADER_EFI_APPLICATION; } if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_FDT)) { Print(L"Add an initrd: "); Status = GetHIInputBoolean (&InitrdSupport); if (EFI_ERROR(Status)) { Status = EFI_ABORTED; goto EXIT; } if (InitrdSupport) { // Create the specific device path node Status = SupportedBootDevice->Support->CreateDevicePathNode (L"initrd", &InitrdPathNodes); if (EFI_ERROR(Status) && Status != EFI_NOT_FOUND) { // EFI_NOT_FOUND is returned on empty input string, but we can boot without an initrd Status = EFI_ABORTED; goto EXIT; } if (InitrdPathNodes != NULL) { // Append the Device Path to the selected device path InitrdPath = AppendDevicePath (SupportedBootDevice->DevicePathProtocol, (CONST EFI_DEVICE_PATH_PROTOCOL *)InitrdPathNodes); // Free the InitrdPathNodes created by Support->CreateDevicePathNode() FreePool (InitrdPathNodes); if (InitrdPath == NULL) { Status = EFI_OUT_OF_RESOURCES; goto EXIT; } } else { InitrdPath = NULL; } } else { InitrdPath = NULL; } Print(L"Arguments to pass to the binary: "); Status = GetHIInputAscii (AsciiCmdLine, BOOT_DEVICE_OPTION_MAX); if (EFI_ERROR(Status)) { Status = EFI_ABORTED; goto FREE_DEVICE_PATH; } CmdLineSize = AsciiStrSize (AsciiCmdLine); InitrdSize = GetDevicePathSize (InitrdPath); OptionalDataSize = sizeof(ARM_BDS_LOADER_ARGUMENTS) + CmdLineSize + InitrdSize; BootArguments = (ARM_BDS_LOADER_ARGUMENTS*)AllocatePool (OptionalDataSize); BootArguments->LinuxArguments.CmdLineSize = CmdLineSize; BootArguments->LinuxArguments.InitrdSize = InitrdSize; CopyMem ((VOID*)(&BootArguments->LinuxArguments + 1), AsciiCmdLine, CmdLineSize); CopyMem ((VOID*)((UINTN)(&BootArguments->LinuxArguments + 1) + CmdLineSize), InitrdPath, InitrdSize); OptionalData = (UINT8*)BootArguments; } else { Print (L"Arguments to pass to the EFI Application: "); Status = GetHIInputStr (CmdLine, BOOT_DEVICE_OPTION_MAX); if (EFI_ERROR (Status)) { Status = EFI_ABORTED; goto EXIT; } OptionalData = (UINT8*)CmdLine; OptionalDataSize = StrSize (CmdLine); } Print(L"Description for this new Entry: "); Status = GetHIInputStr (BootDescription, BOOT_DEVICE_DESCRIPTION_MAX); if (EFI_ERROR(Status)) { Status = EFI_ABORTED; goto FREE_DEVICE_PATH; } // Create new entry BdsLoadOptionEntry = (BDS_LOAD_OPTION_ENTRY*)AllocatePool (sizeof(BDS_LOAD_OPTION_ENTRY)); Status = BootOptionCreate (Attributes, BootDescription, DevicePath, BootType, OptionalData, OptionalDataSize, &BdsLoadOptionEntry->BdsLoadOption); if (!EFI_ERROR(Status)) { InsertTailList (BootOptionsList, &BdsLoadOptionEntry->Link); } FREE_DEVICE_PATH: FreePool (DevicePath); EXIT: if (Status == EFI_ABORTED) { Print(L"\n"); } FreePool(SupportedBootDevice); return Status; }
EFI_STATUS DefineDefaultBootEntries ( VOID ) { BDS_LOAD_OPTION* BdsLoadOption; UINTN Size; EFI_STATUS Status; EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL* EfiDevicePathFromTextProtocol; EFI_DEVICE_PATH* BootDevicePath; UINTN CmdLineSize; UINTN CmdLineAsciiSize; CHAR16* DefaultBootArgument; CHAR8* AsciiDefaultBootArgument; // // If Boot Order does not exist then create a default entry // Size = 0; Status = gRT->GetVariable (L"BootOrder", &gEfiGlobalVariableGuid, NULL, &Size, NULL); if (Status == EFI_NOT_FOUND) { if ((PcdGetPtr(PcdDefaultBootDevicePath) == NULL) || (StrLen ((CHAR16*)PcdGetPtr(PcdDefaultBootDevicePath)) == 0)) { return EFI_UNSUPPORTED; } Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol); if (EFI_ERROR(Status)) { // You must provide an implementation of DevicePathFromTextProtocol in your firmware (eg: DevicePathDxe) DEBUG((EFI_D_ERROR,"Error: Bds requires DevicePathFromTextProtocol\n")); return Status; } BootDevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath ((CHAR16*)PcdGetPtr(PcdDefaultBootDevicePath)); DEBUG_CODE_BEGIN(); // We convert back to the text representation of the device Path to see if the initial text is correct EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol; CHAR16* DevicePathTxt; Status = gBS->LocateProtocol(&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol); ASSERT_EFI_ERROR(Status); DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText (BootDevicePath, TRUE, TRUE); if (StrCmp ((CHAR16*)PcdGetPtr (PcdDefaultBootDevicePath), DevicePathTxt) != 0) { DEBUG ((EFI_D_ERROR, "Device Path given: '%s' Device Path expected: '%s'\n", (CHAR16*)PcdGetPtr (PcdDefaultBootDevicePath), DevicePathTxt)); ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER); } FreePool (DevicePathTxt); DEBUG_CODE_END(); // Create the entry is the Default values are correct if (BootDevicePath != NULL) { // We do not support NULL pointer ASSERT (PcdGetPtr (PcdDefaultBootArgument) != NULL); // // Logic to handle ASCII or Unicode default parameters // if (*(CHAR8*)PcdGetPtr (PcdDefaultBootArgument) == '\0') { CmdLineSize = 0; CmdLineAsciiSize = 0; DefaultBootArgument = NULL; AsciiDefaultBootArgument = NULL; } else if (IsUnicodeString ((CHAR16*)PcdGetPtr (PcdDefaultBootArgument))) { // The command line is a Unicode string DefaultBootArgument = (CHAR16*)PcdGetPtr (PcdDefaultBootArgument); CmdLineSize = StrSize (DefaultBootArgument); // Initialize ASCII variables CmdLineAsciiSize = CmdLineSize / 2; AsciiDefaultBootArgument = AllocatePool (CmdLineAsciiSize); if (AsciiDefaultBootArgument == NULL) { return EFI_OUT_OF_RESOURCES; } UnicodeStrToAsciiStr ((CHAR16*)PcdGetPtr (PcdDefaultBootArgument), AsciiDefaultBootArgument); } else { // The command line is a ASCII string AsciiDefaultBootArgument = (CHAR8*)PcdGetPtr (PcdDefaultBootArgument); CmdLineAsciiSize = AsciiStrSize (AsciiDefaultBootArgument); // Initialize ASCII variables CmdLineSize = CmdLineAsciiSize * 2; DefaultBootArgument = AllocatePool (CmdLineSize); if (DefaultBootArgument == NULL) { return EFI_OUT_OF_RESOURCES; } AsciiStrToUnicodeStr (AsciiDefaultBootArgument, DefaultBootArgument); } BootOptionCreate (LOAD_OPTION_ACTIVE | LOAD_OPTION_CATEGORY_BOOT, (CHAR16*)PcdGetPtr (PcdDefaultBootDescription), BootDevicePath, (UINT8 *)DefaultBootArgument, // OptionalData CmdLineSize, // OptionalDataSize &BdsLoadOption ); FreePool (BdsLoadOption); if (DefaultBootArgument == (CHAR16*)PcdGetPtr (PcdDefaultBootArgument)) { FreePool (AsciiDefaultBootArgument); } else if (DefaultBootArgument != NULL) { FreePool (DefaultBootArgument); } } else { Status = EFI_UNSUPPORTED; } } return Status; }
EFI_STATUS DefineDefaultBootEntries ( VOID ) { BDS_LOAD_OPTION* BdsLoadOption; UINTN Size; EFI_STATUS Status; EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL* EfiDevicePathFromTextProtocol; EFI_DEVICE_PATH* BootDevicePath; UINT8* OptionalData; UINTN OptionalDataSize; ARM_BDS_LOADER_ARGUMENTS* BootArguments; ARM_BDS_LOADER_TYPE BootType; EFI_DEVICE_PATH* InitrdPath; UINTN InitrdSize; UINTN CmdLineSize; UINTN CmdLineAsciiSize; CHAR16* DefaultBootArgument; CHAR8* AsciiDefaultBootArgument; // // If Boot Order does not exist then create a default entry // Size = 0; Status = gRT->GetVariable (L"BootOrder", &gEfiGlobalVariableGuid, NULL, &Size, NULL); if (Status == EFI_NOT_FOUND) { if ((PcdGetPtr(PcdDefaultBootDevicePath) == NULL) || (StrLen ((CHAR16*)PcdGetPtr(PcdDefaultBootDevicePath)) == 0)) { return EFI_UNSUPPORTED; } Status = gBS->LocateProtocol (&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol); if (EFI_ERROR(Status)) { // You must provide an implementation of DevicePathFromTextProtocol in your firmware (eg: DevicePathDxe) DEBUG((EFI_D_ERROR,"Error: Bds requires DevicePathFromTextProtocol\n")); return Status; } BootDevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath ((CHAR16*)PcdGetPtr(PcdDefaultBootDevicePath)); DEBUG_CODE_BEGIN(); // We convert back to the text representation of the device Path to see if the initial text is correct EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol; CHAR16* DevicePathTxt; Status = gBS->LocateProtocol(&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol); ASSERT_EFI_ERROR(Status); DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText (BootDevicePath, TRUE, TRUE); ASSERT (StrCmp ((CHAR16*)PcdGetPtr(PcdDefaultBootDevicePath), DevicePathTxt) == 0); FreePool (DevicePathTxt); DEBUG_CODE_END(); // Create the entry is the Default values are correct if (BootDevicePath != NULL) { BootType = (ARM_BDS_LOADER_TYPE)PcdGet32 (PcdDefaultBootType); // We do not support NULL pointer ASSERT (PcdGetPtr (PcdDefaultBootArgument) != NULL); // // Logic to handle ASCII or Unicode default parameters // if (*(CHAR8*)PcdGetPtr (PcdDefaultBootArgument) == '\0') { CmdLineSize = 0; CmdLineAsciiSize = 0; DefaultBootArgument = NULL; AsciiDefaultBootArgument = NULL; } else if (IsUnicodeString ((CHAR16*)PcdGetPtr (PcdDefaultBootArgument))) { // The command line is a Unicode string DefaultBootArgument = (CHAR16*)PcdGetPtr (PcdDefaultBootArgument); CmdLineSize = StrSize (DefaultBootArgument); // Initialize ASCII variables CmdLineAsciiSize = CmdLineSize / 2; AsciiDefaultBootArgument = AllocatePool (CmdLineAsciiSize); if (AsciiDefaultBootArgument == NULL) { return EFI_OUT_OF_RESOURCES; } UnicodeStrToAsciiStr ((CHAR16*)PcdGetPtr (PcdDefaultBootArgument), AsciiDefaultBootArgument); } else { // The command line is a ASCII string AsciiDefaultBootArgument = (CHAR8*)PcdGetPtr (PcdDefaultBootArgument); CmdLineAsciiSize = AsciiStrSize (AsciiDefaultBootArgument); // Initialize ASCII variables CmdLineSize = CmdLineAsciiSize * 2; DefaultBootArgument = AllocatePool (CmdLineSize); if (DefaultBootArgument == NULL) { return EFI_OUT_OF_RESOURCES; } AsciiStrToUnicodeStr (AsciiDefaultBootArgument, DefaultBootArgument); } if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_FDT)) { InitrdPath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath ((CHAR16*)PcdGetPtr(PcdDefaultBootInitrdPath)); InitrdSize = GetDevicePathSize (InitrdPath); OptionalDataSize = sizeof(ARM_BDS_LOADER_ARGUMENTS) + CmdLineAsciiSize + InitrdSize; BootArguments = (ARM_BDS_LOADER_ARGUMENTS*)AllocatePool (OptionalDataSize); if (BootArguments == NULL) { return EFI_OUT_OF_RESOURCES; } BootArguments->LinuxArguments.CmdLineSize = CmdLineAsciiSize; BootArguments->LinuxArguments.InitrdSize = InitrdSize; CopyMem ((VOID*)(BootArguments + 1), AsciiDefaultBootArgument, CmdLineAsciiSize); CopyMem ((VOID*)((UINTN)(BootArguments + 1) + CmdLineAsciiSize), InitrdPath, InitrdSize); OptionalData = (UINT8*)BootArguments; } else { OptionalData = (UINT8*)DefaultBootArgument; OptionalDataSize = CmdLineSize; } BootOptionCreate (LOAD_OPTION_ACTIVE | LOAD_OPTION_CATEGORY_BOOT, (CHAR16*)PcdGetPtr(PcdDefaultBootDescription), BootDevicePath, BootType, OptionalData, OptionalDataSize, &BdsLoadOption ); FreePool (BdsLoadOption); if (DefaultBootArgument == (CHAR16*)PcdGetPtr (PcdDefaultBootArgument)) { FreePool (AsciiDefaultBootArgument); } else if (DefaultBootArgument != NULL) { FreePool (DefaultBootArgument); } } else { Status = EFI_UNSUPPORTED; } } return Status; }