On Tue, 2012-11-13 at 16:18 +0100, Laszlo Ersek wrote:
> On 11/12/12 21:55, Laszlo Ersek wrote:
> > On 10/29/12 01:01, Jordan Justen wrote:
> 
> >> +
> >> +
> >> +STATIC
> >>  EFI_STATUS
> >> -TryRunningQemuKernel (
> >> -  VOID
> >> +TryRunningPeCoffImage (
> >> +  IN VOID                   *SetupBuf,
> >> +  IN UINTN                  SetupSize,
> >> +  IN UINTN                  KernelSize
> >> +  )
> >> +{
> >> +  EFI_STATUS                Status;
> >> +  UINTN                     PeImageSize;
> >> +  VOID                      *PeImageData;
> >> +  EFI_HANDLE                ImageHandle;
> >> +  EFI_HANDLE                DevicePathHandle;
> >> +  MEMMAP_IMAGE_DEVICE_PATH  DevicePath;
> >> +
> >> +  PeImageData = NULL;
> >> +  PeImageSize = 0;
> >> +  Status = EFI_SUCCESS;
> >> +
> >> +  //
> >> +  // The first part of the PE/COFF image was loaded from the 'kernel 
> >> setup'
> >> +  // area. QEMU will put the remaining portion in the 'kernel data' area.
> >> +  //
> >> +  // We combine these two items into a single buffer to retrieve the 
> >> original
> >> +  // PE/COFF image.
> >> +  //
> >> +  PeImageSize = SetupSize + KernelSize;
> 
> Let's assume the sum won't ever overflow.
> 
> >> +  PeImageData = AllocatePages (EFI_SIZE_TO_PAGES (PeImageSize));
> >> +  if (PeImageData == NULL) {
> >> +    Status = EFI_OUT_OF_RESOURCES;
> >> +    goto FreeAndReturn;
> >> +  }
> >> +  CopyMem (PeImageData, SetupBuf, SetupSize);
> >> +
> >> +  DEBUG ((EFI_D_INFO, "Remaining PE/COFF image size: 0x%x\n", (UINT32) 
> >> KernelSize));
> >> +  DEBUG ((EFI_D_INFO, "Reading PE/COFF image ..."));
> >> +  QemuFwCfgSelectItem (QemuFwCfgItemKernelData);
> >> +  QemuFwCfgReadBytes (KernelSize, ((UINT8*) PeImageData) + SetupSize);
> >> +  DEBUG ((EFI_D_INFO, " [done]\n"));
> >> +
> >> +  //
> >> +  // Create a device path for the image
> >> +  //
> >> +  CopyMem ((VOID*) &DevicePath,
> >> +           (VOID*) &mMemmapImageDevicePathTemplate,
> >> +           sizeof (DevicePath));
> 
> Ah this makes me ask another question regarding
> MEMMAP_IMAGE_DEVICE_PATH: shouldn't it be packed? 

Yes, you are correct. It should be packed.

> AFAIK a device path is
> traversed node-by-node using "EFI_DEVICE_PATH_PROTOCOL.Length" at the
> beginning of each ("derived") node. Without packing, a compiler is
> theoretically allowed to insert padding between the two fields of
> MEMMAP_IMAGE_DEVICE_PATH, throwing off the traversal.
> 
> 
> >> +  DevicePath.MemMapDevPath.StartingAddress = (UINTN) PeImageData;
> >> +  DevicePath.MemMapDevPath.EndingAddress =
> >> +    DevicePath.MemMapDevPath.StartingAddress + PeImageSize;
> 
> Is "EndingAddress" exclusive?
>
> - "DuetPkg/FvbRuntimeService/FWBlockService.c" suggests it is inclusive
> (ie. base + size - 1).
> - OTOH, "ArmPkg/Library/BdsLib/BdsFilePath.c" suggests it is exclusive
> (ie. size = ending - starting)
> - The field name itself suggests inclusive.

The UEFI spec seems vague, but
MdeModulePkg/Core/Dxe/FwVolBlock/FwVolBlock.c
also suggests inclusive, so I should probably go with that.

> >> +  DevicePathHandle = NULL;
> >> +  Status = gBS->InstallProtocolInterface (
> >> +                  &DevicePathHandle,
> >> +                  &gEfiDevicePathProtocolGuid,
> >> +                  EFI_NATIVE_INTERFACE,
> >> +                  (VOID*) &DevicePath
> >> +                  );
> 
> Status check missing.
> 
> BTW why do we need to install the protocol interace on DevicePath for
> the rest of the world?

The new UEFI shell required this to be present.

> >> +
> >> +  //
> >> +  // Load and start the PE/COFF image
> >> +  //
> >> +  ImageHandle = NULL;
> >> +  Status = gBS->LoadImage (
> >> +                  FALSE,
> >> +                  gImageHandle,
> >> +                  (VOID*) &DevicePath,
> >> +                  PeImageData,
> >> +                  PeImageSize,
> >> +                  &ImageHandle
> >> +                  );
> 
> Do we need both DevicePath and PeImageData/PeImageSize here? (Just
> trying to learn, the spec of LoadImage() is hard to interpret.)

For UEFI in general, I think either can be used. In this
situation a pointer+size is the most useful, but like I
mentioned above, I added the device path to allow the new
UEFI shell to run.

> >> +  DEBUG ((EFI_D_INFO, "Loading PE/COFF image -> %r\n", Status));
> >> +
> >> +  if (!EFI_ERROR (Status)) {
> >> +    DEBUG ((EFI_D_INFO, "Starting PE/COFF image ...\n"));
> >> +    Status = gBS->StartImage (ImageHandle, NULL, NULL);
> >> +    DEBUG ((EFI_D_INFO, "PE/COFF image exited -> %r\n", Status));
> >> +  }
> 
> Again, I do not understand UnloadImage() spec: what happens if the image
> - has been loaded,
> - has been started,
> - does not have an Unload entry point?
> 
> UnloadImage() returns EFI_UNSUPPORTED. That's OK, but what happens to
> the image when StartImage() returns? Is it automatically unloaded, or
> leaked forever?

The DXE Core will automatically unload applications regardless of
the return value, and it will unload drivers if an error value
is returned.

MdeModulePkg/Core/Dxe/Image/Image.c

> >> +
> >> +  //
> >> +  // Uninstall the device path for the image
> >> +  //
> >> +  Status = gBS->UninstallProtocolInterface (
> >> +                  DevicePathHandle,
> >> +                  &gEfiDevicePathProtocolGuid,
> >> +                  (VOID*) &DevicePath
> >> +                  );
> 
> This overwrites the status returned by the image. May not matter in
> practice, but I think the intent is to propagate it.

Yes, I think you are right.

Thanks,

-Jordan

> >> +  ASSERT_EFI_ERROR (Status);
> >> +
> >> +FreeAndReturn:
> >> +  if (PeImageData != NULL) {
> >> +    FreePages (PeImageData, EFI_SIZE_TO_PAGES (PeImageSize));
> >> +  }
> >> +
> >> +  return Status;
> >> +}
> >> +
> >> +
> 
> >> +EFI_STATUS
> >> +TryRunningQemuKernel (
> >> +  VOID
> >> +  )
> >> +{
> >> +  EFI_STATUS                Status;
> >> +  UINTN                     SetupSize;
> >> +  VOID                      *SetupBuf;
> >> +  UINTN                     KernelSize;
> >> +
> >> +  SetupBuf = NULL;
> >> +  SetupSize = 0;
> >> +
> >> +  if (!QemuFwCfgIsAvailable ()) {
> >> +    return EFI_NOT_FOUND;
> >> +  }
> >> +
> >> +  QemuFwCfgSelectItem (QemuFwCfgItemKernelSize);
> >> +  KernelSize = (UINTN) QemuFwCfgRead64 ();
> >> +
> >> +  QemuFwCfgSelectItem (QemuFwCfgItemKernelSetupSize);
> >> +  SetupSize = (UINTN) QemuFwCfgRead64 ();
> >> +
> >> +  if (KernelSize == 0 || SetupSize == 0) {
> >> +    DEBUG ((EFI_D_INFO, "qemu -kernel was not used.\n"));
> >> +    return EFI_NOT_FOUND;
> >> +  }
> >> +
> >> +  SetupBuf = LoadLinuxAllocateKernelSetupPages (EFI_SIZE_TO_PAGES 
> >> (SetupSize));
> >> +  if (SetupBuf == NULL) {
> >> +    DEBUG ((EFI_D_ERROR, "Unable to allocate memory for kernel 
> >> setup!\n"));
> >> +    return EFI_OUT_OF_RESOURCES;
> >> +  }
> >> +
> >> +  DEBUG ((EFI_D_INFO, "Setup size: 0x%x\n", (UINT32) SetupSize));
> >> +  DEBUG ((EFI_D_INFO, "Reading kernel setup image ..."));
> >> +  QemuFwCfgSelectItem (QemuFwCfgItemKernelSetupData);
> >> +  QemuFwCfgReadBytes (SetupSize, SetupBuf);
> >> +  DEBUG ((EFI_D_INFO, " [done]\n"));
> >> +
> >> +  if (LooksLikeAPeCoffImage (SetupBuf, SetupSize)) {
> >> +    Status = TryRunningPeCoffImage (SetupBuf, SetupSize, KernelSize);
> >> +  } else {
> >> +    Status = TryRunningKernelImage (SetupBuf, SetupSize, KernelSize);
> >> +  }
> >> +
> >> +  if (SetupBuf != NULL) {
> >> +    FreePages (SetupBuf, EFI_SIZE_TO_PAGES (SetupSize));
> >> +  }
> 
> Sorry for not noticing this earlier: SetupBuf is never NULL here.
> 
> >> +
> >> +  return Status;
> >> +}
> 
> No more comments.
> 
> Thanks,
> Laszlo



------------------------------------------------------------------------------
Monitor your physical, virtual and cloud infrastructure from a single
web console. Get in-depth insight into apps, servers, databases, vmware,
SAP, cloud infrastructure, etc. Download 30-day Free Trial.
Pricing starts from $795 for 25 servers or applications!
http://p.sf.net/sfu/zoho_dev2dev_nov
_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/edk2-devel

Reply via email to