示例#1
0
文件: bcdopt.c 项目: Strongc/reactos
/*++
 * @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;
}
示例#2
0
文件: efiemu.c 项目: CSRedRat/reactos
/*++
 * @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;
}