> On Mar 26, 2015, at 10:42 AM, David Cox <[email protected]> wrote:
> 
> Hi,
>  
> I have an efi I am trying to execute.  I did not create the EFI so have no 
> source.  Loadimage(…) works, but startimage(…) fails with status 3

This is the code for gBS->StartImage()

https://svn.code.sf.net/p/edk2/code/trunk/edk2/MdeModulePkg/Core/Dxe/Image/Image.c
 
<https://svn.code.sf.net/p/edk2/code/trunk/edk2/MdeModulePkg/Core/Dxe/Image/Image.c>
/**
  Transfer control to a loaded image's entry point.

  @param  ImageHandle             Handle of image to be started.
  @param  ExitDataSize            Pointer of the size to ExitData
  @param  ExitData                Pointer to a pointer to a data buffer that
                                  includes a Null-terminated string,
                                  optionally followed by additional binary data.
                                  The string is a description that the caller 
may
                                  use to further indicate the reason for the
                                  image's exit.

  @retval EFI_INVALID_PARAMETER   Invalid parameter
  @retval EFI_OUT_OF_RESOURCES    No enough buffer to allocate
  @retval EFI_SECURITY_VIOLATION  The current platform policy specifies that 
the image should not be started.
  @retval EFI_SUCCESS             Successfully transfer control to the image's
                                  entry point.

**/
EFI_STATUS
EFIAPI
CoreStartImage (
  IN EFI_HANDLE  ImageHandle,
  OUT UINTN      *ExitDataSize,
  OUT CHAR16     **ExitData  OPTIONAL
  )
{
  EFI_STATUS                    Status;
  LOADED_IMAGE_PRIVATE_DATA     *Image;
  LOADED_IMAGE_PRIVATE_DATA     *LastImage;
  UINT64                        HandleDatabaseKey;
  UINTN                         SetJumpFlag;
  UINT64                        Tick;
  EFI_HANDLE                    Handle;

  Tick = 0;
  Handle = ImageHandle;

  Image = CoreLoadedImageInfo (ImageHandle);
  if (Image == NULL  ||  Image->Started) {
    return EFI_INVALID_PARAMETER;
  }
  if (EFI_ERROR (Image->LoadImageStatus)) {
    return Image->LoadImageStatus;
  }

  //
  // The image to be started must have the machine type supported by DxeCore.
  //
  if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Image->Machine)) {
    //
    // Do not ASSERT here, because image might be loaded via 
EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED
    // But it can not be started.
    //
    DEBUG ((EFI_D_ERROR, "Image type %s can't be started ", 
GetMachineTypeName(Image->Machine)));
    DEBUG ((EFI_D_ERROR, "on %s UEFI system.\n", 
GetMachineTypeName(mDxeCoreImageMachineType)));
    return EFI_UNSUPPORTED;
  }

  PERF_CODE (
    Tick = GetPerformanceCounter ();
  );


  //
  // Push the current start image context, and
  // link the current image to the head.   This is the
  // only image that can call Exit()
  //
  HandleDatabaseKey = CoreGetHandleDatabaseKey ();
  LastImage         = mCurrentImage;
  mCurrentImage     = Image;
  Image->Tpl        = gEfiCurrentTpl;

  //
  // Set long jump for Exit() support
  // JumpContext must be aligned on a CPU specific boundary.
  // Overallocate the buffer and force the required alignment
  //
  Image->JumpBuffer = AllocatePool (sizeof (BASE_LIBRARY_JUMP_BUFFER) + 
BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT);
  if (Image->JumpBuffer == NULL) {
    //
    // Image may be unloaded after return with failure,
    // then ImageHandle may be invalid, so use NULL handle to record perf log.
    //
    PERF_START (NULL, "StartImage:", NULL, Tick);
    PERF_END (NULL, "StartImage:", NULL, 0);
    return EFI_OUT_OF_RESOURCES;
  }
  Image->JumpContext = ALIGN_POINTER (Image->JumpBuffer, 
BASE_LIBRARY_JUMP_BUFFER_ALIGNMENT);

  SetJumpFlag = SetJump (Image->JumpContext);
  //
  // The initial call to SetJump() must always return 0.
  // Subsequent calls to LongJump() cause a non-zero value to be returned by 
SetJump().
  //
  if (SetJumpFlag == 0) {
    RegisterMemoryProfileImage (Image, (Image->ImageContext.ImageType == 
EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION ? EFI_FV_FILETYPE_APPLICATION : 
EFI_FV_FILETYPE_DRIVER));
    //
    // Call the image's entry point
    //
    Image->Started = TRUE;
    Image->Status = Image->EntryPoint (ImageHandle, Image->Info.SystemTable);

    //
    // Add some debug information if the image returned with error.
    // This make the user aware and check if the driver image have already 
released
    // all the resource in this situation.
    //
    DEBUG_CODE_BEGIN ();
      if (EFI_ERROR (Image->Status)) {
        DEBUG ((DEBUG_ERROR, "Error: Image at %11p start failed: %r\n", 
Image->Info.ImageBase, Image->Status));
      }
    DEBUG_CODE_END ();

    //
    // If the image returns, exit it through Exit()
    //
    CoreExit (ImageHandle, Image->Status, 0, NULL);
  }

  //
  // Image has completed.  Verify the tpl is the same
  //
  ASSERT (Image->Tpl == gEfiCurrentTpl);
  CoreRestoreTpl (Image->Tpl);

  CoreFreePool (Image->JumpBuffer);

  //
  // Pop the current start image context
  //
  mCurrentImage = LastImage;

  //
  // Go connect any handles that were created or modified while the image 
executed.
  //
  CoreConnectHandlesByKey (HandleDatabaseKey);

  //
  // Handle the image's returned ExitData
  //
  DEBUG_CODE_BEGIN ();
    if (Image->ExitDataSize != 0 || Image->ExitData != NULL) {

      DEBUG ((DEBUG_LOAD, "StartImage: ExitDataSize %d, ExitData %p", 
(UINT32)Image->ExitDataSize, Image->ExitData));
      if (Image->ExitData != NULL) {
        DEBUG ((DEBUG_LOAD, " (%hs)", Image->ExitData));
      }
      DEBUG ((DEBUG_LOAD, "\n"));
    }
  DEBUG_CODE_END ();

  //
  //  Return the exit data to the caller
  //
  if (ExitData != NULL && ExitDataSize != NULL) {
    *ExitDataSize = Image->ExitDataSize;
    *ExitData     = Image->ExitData;
  } else {
    //
    // Caller doesn't want the exit data, free it
    //
    CoreFreePool (Image->ExitData);
    Image->ExitData = NULL;
  }

  //
  // Save the Status because Image will get destroyed if it is unloaded.
  //
  Status = Image->Status;

  //
  // If the image returned an error, or if the image is an application
  // unload it
  //
  if (EFI_ERROR (Image->Status) || Image->Type == 
EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) {
    CoreUnloadAndCloseImage (Image, TRUE);
    //
    // ImageHandle may be invalid after the image is unloaded, so use NULL 
handle to record perf log.
    //
    Handle = NULL;
  }

  //
  // Done
  //
  PERF_START (Handle, "StartImage:", NULL, Tick);
  PERF_END (Handle, "StartImage:", NULL, 0);
  return Status;
}


> , unsupported.  If I build a simple hello world application, it runs this OK.
>  
> Things I’ve checked, imagecodetype is 1 (same as launching application). 

EfiLoaderCode is what you would expect for an Application. 

> The image size is very much larger than the binary size on disk when queried 
> by loadedimageprotocol.
>  

This is possible if the PE/COFF image has a file size that is smaller than the 
virtual size. In this case the extra space is zeroed filled. So it is usually 
the BSS that gets this treatment. 

Can you dump the PE/COFF image?
VC++: DUMPBIN.EXE /ALL
gcc: objdump -p

> I have tried converting binary into a C byte array and including in launch 
> application (packing set to 8).  Then allocating from pool and copying said 
> byte array into pooled memory buffer, passing this as source buffer to 
> loadimage(…).  Again it works with my helloworld application but not with the 
> actual binary I want to run.
>  

I’m not sure what that would prove? The path, other than reading in the binary 
would be identical is LoadImage()/StartImage()? 

> I have tried the efi binary shell package and I can successfully run the 
> problem binary application from there fine.
>  
> Any suggestions would be very helpful,
>  

Is your code calling gBS->LoadImage()/gBS->StartImage()? Maybe the bug is in 
that code?

Thanks,

Andrew Fish


> Regards,
>  
> Dave Cox
> 

------------------------------------------------------------------------------
Dive into the World of Parallel Programming The Go Parallel Website, sponsored
by Intel and developed in partnership with Slashdot Media, is your hub for all
things parallel software development, from weekly thought leadership blogs to
news, videos, case studies, tutorials and more. Take a look and join the 
conversation now. http://goparallel.sourceforge.net/
_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/edk2-devel

Reply via email to