/*++ * @name BlGetBootOptionListSize * * The BlGetBootOptionListSize routine * * @param BcdOption * UEFI Image Handle for the current loaded application. * * @return Size of the BCD option * *--*/ ULONG BlGetBootOptionListSize ( _In_ PBL_BCD_OPTION BcdOption ) { ULONG Size = 0, NextOffset = 0; PBL_BCD_OPTION NextOption; /* Loop all the options*/ do { /* Move to the next one */ NextOption = (PBL_BCD_OPTION)((ULONG_PTR)BcdOption + NextOffset); /* Compute the size of the next one */ Size += BlGetBootOptionSize(NextOption); /* Update the offset */ NextOffset = NextOption->NextEntryOffset; } while (NextOffset); /* Return final computed size */ return Size; }
/*++ * @name EfiInitpCreateApplicationEntry * * The EfiInitpCreateApplicationEntry routine * * @param SystemTable * UEFI Image Handle for the current loaded application. * * @param Entry * Pointer to the UEFI System Table. * * @param MaximumLength * Pointer to the UEFI System Table. * * @param DevicePath * Pointer to the UEFI System Table. * * @param FilePath * Pointer to the UEFI System Table. * * @param LoadOptions * Pointer to the UEFI System Table. * * @param LoadOptionsSize * Pointer to the UEFI System Table. * * @param Flags * Pointer to the UEFI System Table. * * @param ResultLength * Pointer to the UEFI System Table. * * @param AppEntryDevice * Pointer to the UEFI System Table. * * @return None * *--*/ VOID EfiInitpCreateApplicationEntry ( __in EFI_SYSTEM_TABLE *SystemTable, __in PBL_APPLICATION_ENTRY Entry, __in ULONG MaximumLength, __in EFI_DEVICE_PATH *DevicePath, __in EFI_DEVICE_PATH *FilePath, __in PWCHAR LoadOptions, __in ULONG LoadOptionsSize, __in ULONG Flags, __out PULONG ResultLength, __out PBL_DEVICE_DESCRIPTOR *AppEntryDevice ) { PBL_WINDOWS_LOAD_OPTIONS WindowsOptions; PWCHAR ObjectString, CommandLine; PBL_BCD_OPTION Option, PreviousOption; ULONG HeaderSize, TotalOptionSize, Size, CommandLineSize, RemainingSize; NTSTATUS Status; UNICODE_STRING GuidString; GUID ObjectGuid; PBCD_DEVICE_OPTION BcdDevice; BOOLEAN HaveBinaryOptions, HaveGuid; PBL_FILE_PATH_DESCRIPTOR OsPath; EFI_DEVICE_PATH *OsDevicePath; /* Initialize everything */ TotalOptionSize = 0; *AppEntryDevice = NULL; HeaderSize = 0; /* Check if the load options are in binary Windows format */ WindowsOptions = (PBL_WINDOWS_LOAD_OPTIONS)LoadOptions; if ((WindowsOptions != NULL) && (LoadOptionsSize >= sizeof(BL_WINDOWS_LOAD_OPTIONS)) && (WindowsOptions->Length >= sizeof(BL_WINDOWS_LOAD_OPTIONS)) && !(strncmp(WindowsOptions->Signature, "WINDOWS", 7))) { /* They are, so firmware must have loaded us -- extract arguments */ CommandLine = WindowsOptions->LoadOptions; CommandLineSize = LoadOptionsSize - FIELD_OFFSET(BL_WINDOWS_LOAD_OPTIONS, LoadOptions); /* Remember that we used binary options */ HaveBinaryOptions = TRUE; } else { /* Nope -- so treat them as raw command-line options */ CommandLine = LoadOptions; CommandLineSize = LoadOptionsSize; /* No binary options */ HaveBinaryOptions = FALSE; } /* EFI uses UTF-16LE, like NT, so convert to characters */ CommandLineSize /= sizeof(WCHAR); if (CommandLineSize != 0) { /* And check if the options are not NULL-terminated */ if (wcsnlen(CommandLine, CommandLineSize) == CommandLineSize) { /* NULL-terminate them */ CommandLine[CommandLineSize - 1] = UNICODE_NULL; } } /* Begin by making sure we at least have space for the app entry header */ RemainingSize = MaximumLength; if (RemainingSize < sizeof(BL_APPLICATION_ENTRY)) { Status = STATUS_INVALID_PARAMETER; goto Quickie; } /* On exit, return that we've at least consumed this much */ HeaderSize = FIELD_OFFSET(BL_APPLICATION_ENTRY, BcdData); /* Zero out the header, and write down the signature */ RtlZeroMemory(Entry, sizeof(BL_APPLICATION_ENTRY)); RtlCopyMemory(Entry->Signature, BL_APP_ENTRY_SIGNATURE, 7); /* Check if a BCD object was passed on the command-line */ ObjectString = wcsstr(CommandLine, L"BCDOBJECT="); if (ObjectString != NULL) { /* Convert the BCD object to a GUID */ RtlInitUnicodeString(&GuidString, ObjectString + 10); RtlGUIDFromString(&GuidString, &ObjectGuid); /* Store it in the application entry */ Entry->Guid = ObjectGuid; /* Remember one was passed */ HaveGuid = TRUE; } else { /* Remember that no identifier was passed */ Entry->Flags |= BL_APPLICATION_ENTRY_FLAG_NO_GUID; HaveGuid = FALSE; } /* At this point, the header is consumed, and we must now handle BCD options */ RemainingSize -= FIELD_OFFSET(BL_APPLICATION_ENTRY, BcdData); /* Convert the device path into a BCD option */ Status = EfiInitpConvertEfiDevicePath(DevicePath, BcdLibraryDevice_ApplicationDevice, &Entry->BcdData, RemainingSize); if (!NT_SUCCESS(Status)) { /* We failed, so mark the option as such and return an empty one */ Entry->BcdData.Empty = TRUE; TotalOptionSize = sizeof(BL_BCD_OPTION); goto Quickie; } /* Extract the device descriptor and return it */ BcdDevice = (PVOID)((ULONG_PTR)&Entry->BcdData + Entry->BcdData.DataOffset); *AppEntryDevice = &BcdDevice->DeviceDescriptor; /* Calculate how big this option was and consume that from the buffer */ TotalOptionSize = BlGetBootOptionSize(&Entry->BcdData); RemainingSize -= TotalOptionSize; /* Calculate where the next option should go */ Option = (PVOID)((ULONG_PTR)&Entry->BcdData + TotalOptionSize); /* Check if we're PXE booting or not */ if ((*AppEntryDevice)->DeviceType == UdpDevice) { /* lol */ Status = STATUS_NOT_IMPLEMENTED; } else { /* Convert the local file path into a BCD option */ Status = EfiInitpConvertEfiFilePath(FilePath, BcdLibraryString_ApplicationPath, Option, RemainingSize); } /* Bail out on failure */ if (!NT_SUCCESS(Status)) { goto Quickie; } /* The next option is right after this one */ Entry->BcdData.NextEntryOffset = TotalOptionSize; /* Now compute the size of the next option, and add to the rolling sum */ Size = BlGetBootOptionSize(Option); TotalOptionSize += Size; /* Remember the previous option so we can update its next offset */ PreviousOption = Option; /* Consume the option from the buffer */ RemainingSize -= Size; /* Calculate where the next option should go */ Option = (PVOID)((ULONG_PTR)Option + Size); /* Check if we were using binary options without a BCD GUID */ if ((HaveBinaryOptions) && !(HaveGuid)) { /* Then this means we have to convert the OS paths to BCD too */ WindowsOptions = (PBL_WINDOWS_LOAD_OPTIONS)LoadOptions; OsPath = (PVOID)((ULONG_PTR)WindowsOptions + WindowsOptions->OsPathOffset); /* IS the OS path in EFI format? */ if ((OsPath->Length > (ULONG)FIELD_OFFSET(BL_FILE_PATH_DESCRIPTOR, Path)) && (OsPath->PathType == EfiPath)) { /* Convert the device portion */ OsDevicePath = (EFI_DEVICE_PATH*)OsPath->Path; Status = EfiInitpConvertEfiDevicePath(OsDevicePath, BcdOSLoaderDevice_OSDevice, Option, RemainingSize); if (!NT_SUCCESS(Status)) { goto Quickie; } /* Update the offset of the previous option */ PreviousOption->NextEntryOffset = (ULONG_PTR)Option - (ULONG_PTR)&Entry->BcdData; /* Now compute the size of the next option, and add to the rolling sum */ Size = BlGetBootOptionSize(Option); TotalOptionSize += Size; /* Remember the previous option so we can update its next offset */ PreviousOption = Option; /* Consume the option from the buffer */ RemainingSize -= Size; /* Calculate where the next option should go */ Option = (PVOID)((ULONG_PTR)Option + Size); /* Convert the path option */ Status = EfiInitpConvertEfiFilePath(OsDevicePath, BcdOSLoaderString_SystemRoot, Option, RemainingSize); if (!NT_SUCCESS(Status)) { goto Quickie; } /* Update the offset of the previous option */ PreviousOption->NextEntryOffset = (ULONG_PTR)Option - (ULONG_PTR)&Entry->BcdData; /* Now compute the size of the next option, and add to the rolling sum */ Size = BlGetBootOptionSize(Option); TotalOptionSize += Size; /* Remember the previous option so we can update its next offset */ PreviousOption = Option; /* Consume the option from the buffer */ RemainingSize -= Size; /* Calculate where the next option should go */ Option = (PVOID)((ULONG_PTR)Option + Size); } } /* Now convert everything else */ AhCreateLoadOptionsList(CommandLine, &Entry->BcdData, RemainingSize, &TotalOptionSize, &PreviousOption, &Size); Quickie: /* Return the final size */ *ResultLength = HeaderSize + TotalOptionSize; }