> On Jun 16, 2022, at 1:17 PM, Ayush Singh <ayushdevel1...@gmail.com> wrote:
> 
> Thanks for the great answer. After some discussion in the zulip [1], I
> have some approaches that I will try first.
> 
> As for calling C, EFIABI from Rust, yes, it is quite well supported.
> Rust also has a specific EFIABI now, since some EFI platforms don't
> use C calling conventions.
> 
> As for the entry point, llvm has an `-entry:efi_main` that can be used
> to define the entry function for UEFI targets. I just was not sure I
> could integrate it with the actual `main()` function.
> 

For the C builds the tools_def.txt file uses  $(IMAGE_ENTRY_POINT). The build 
maps that over to the _ModelEntryPoint label I mentioned. It would probably be 
good to sue the same symbol. 

The C we have is free standing so there is nothing that is setup for the C 
language, other that libs the user asked for.

> In normal Rust, the control flow is somewhat like this: crt0 -> libc
> main -> rust lang_start -> rust lang_start_internal -> rust main
> 
> In UEFI, I would have to do something like this: efi_main -> rust
> lang_start -> rust lang_start_internal -> rust main
> 

The edk2 way to do this seems to me is to create an edk2 RustEntryPoint lib 
that models the edk2 *EntryPointLib [1]. The entry point would be  
_ModelEntryPoint.

I’m not 100% clear on all the dependencies but the big picture is for C edk2 
injects code between the entry point and the main function. I think you will 
want that in your Rust world.

The other thing you need to manage is the entry point hands-off  the only way 
to bind to all the EFI Services so that needs to make it into your Rust world. 

EFI_STATUS
EFIAPI
_ModuleEntryPoint (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
The Apps need access to SystemTable to do just about anything. The ImageHandle 
lets them get access to args and info on how the driver/app was loaded. 

We have different flavors of these entry point libs as the handoff, and 
sometimes entry exit behavior are different:
$ git grep 'EntryPoint|' -- \*.inf | grep LIBRARY_CLASS
MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf:18:  LIBRARY_CLASS       
           = DxeCoreEntryPoint|DXE_CORE
MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf:18:  LIBRARY_CLASS       
           = PeiCoreEntryPoint|PEI_CORE
MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf:18:  LIBRARY_CLASS             
     = PeimEntryPoint|PEIM
MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.inf:21:
  LIBRARY_CLASS                  = StandaloneMmDriverEntryPoint|MM_STANDALONE
MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf:18:  
LIBRARY_CLASS                  = UefiApplicationEntryPoint|UEFI_APPLICATION
MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf:18:  LIBRARY_CLASS 
                 = UefiDriverEntryPoint|DXE_DRIVER DXE_RUNTIME_DRIVER 
UEFI_DRIVER SMM_CORE DXE_SMM_DRIVER
StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/StandaloneMmCoreEntryPoint.inf:18:
  LIBRARY_CLASS                  = StandaloneMmCoreEntryPoint|MM_CORE_STANDALONE

I think what this means from a practical point after reading your Rust thread 
is:
1) Have some custom code, per driver type, to maybe convert the EFI/PEI/edk2 
define entry point arguments maybe into standard Rust args. 
  argc = 2
  argv[0] = ImageHandle
  argv[1] =  *SystemTable

2) Then you can call the common Rust init flow from your link. 

3) rt_entry() is custom for edk2. It would basically do the same things as the 
edk2 C *EntryPoint libs _ModuleEntryPoint() functions. Call the auto generated 
lib constructor functions, call the auto generated entry point function that 
calls the function in the users Rust code. Call the lib destructor. Also 
provide support for the Exit function. 

You can kind of hard code bits to get started, but If you think about it this 
way I think it will be easier to layer in edk2 like build features as we grow 
the Rust support. 

You could get really fancy and pass the mode BASE/PEIM/DXE in argv[0], and the 
args in args[1], …. By doing that you might need small stubs that are mode 
specific to capture the different entry point APIs, but all the other lib 
infrastructure could be common. The little tiny entry stub libs could depend on 
the common lib so the INF files would only need to specify the entry point stub 
lib.

[1] 
https://github.com/tianocore/edk2/blob/master/MdePkg/Library/UefiApplicationEntryPoint/ApplicationEntryPoint.c

Thanks,

Andrew Fish

> The problem was that I couldn't find a way to go from `efi_main ->
> rust lang_start` earlier. After all, it is such a low-level detail
> that there is almost no documentation for anything that happens before
> `rust lang_start`. Still, I do have some idea now, so will see how it
> goes.
> 
> Ayush Singh
> 
> [1]: 
> (https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp/topic/Run.20a.20function.20before.20.60lang_start.60/near/286376012)
> 
> On Fri, Jun 17, 2022 at 12:06 AM Andrew Fish <af...@apple.com> wrote:
>> 
>> 
>> 
>>> On Jun 16, 2022, at 7:20 AM, Ayush Singh <ayushdevel1...@gmail.com> wrote:
>>> 
>>> Hello everyone, I wanted to ask if the edk2 build system also links to
>>> crt0-efi, like GNU-EFI?
>>> 
>>> If yes, I would also like to see how that is actually implemented. If
>>> not, how does edk2 support custom entry functions? It is possible with
>>> llvm backend but I am not sure how it is done in GCC and am curious,
>>> 
>> 
>> The general answer for edk2 is and library that a `CONSTRUCTOR =` statement 
>> in its INF that lib constructor will get called when the Driver/App is 
>> started.
>> 
>> The actually entry point for a Driver/App is _ModuleEntryPoint(). The 
>> typical way it is done is this is implemented in a phase specific 
>> library[1]. This phase specific basically calls 3 C functions that got 
>> generated by the build: ProcessLibraryConstructorList(), 
>> ProcessModuleEntryPointList(), and ProcessLibraryDestructorList(). The 
>> library constructor/destructors functions call the lib  
>> constructor/destructors function based in the sequence of the dependency 
>> graph of the libraries that get pulled in.
>> 
>>> Currently, rust does not support the custom implementation of
>>> `lang_start` (which is started by crt0 in most platforms), so I was
>>> trying to find ways to be able to use custom crt0 which sets up
>>> `SystemTable` and `SystemHandler` and start the `lang_start` from it.
>>> This way, the user will be able to call the normal `main` function
>>> rather than using the `no_main` feature.
>>> 
>> 
>> If you look in the build output of an edk2 C driver/app you will see an 
>> AutoGen.h and AutoGen.c file. This was the C code the build system 
>> autogenerated to glue everything together. It manages gluing in the libs, 
>> abstracting the PCD implementation, and adding C constants for EFI_GUID 
>> values.
>> 
>> Sorry I don’t know Rust yet. Is it possible to call C, EFIABI, from Rust 
>> code? If yes maybe what you need is a Rust ModuleEntryPoint that can call 
>> the C library constructor and a C EFIABI entry function for your Rust. I’m 
>> not sure how you manage dealing with C includes in Rust? With C++ you can 
>> just decorate them.
>> 
>> I guess the other 100% Rust option is to know the INF is building Rust (INF 
>> has Code.rs files) and build Rust (or Rust compatible) AutoGen
>> 
>>> My blog post [1] shows how we currently use the `efi_main` function.
>>> 
>>> Yours sincerely,
>>> Ayush Singh
>>> 
>>> [1]: (https://www.programmershideaway.xyz/post5/)
>>> 
>>> 
>> 
>> [1] 
>> https://github.com/tianocore/edk2/blob/master/MdePkg/Library/UefiApplicationEntryPoint/ApplicationEntryPoint.c
>> 
>> Thanks,
>> 
>> Andrew Fish
>> 
>> 
>>> 
>>> 
>>> 
>> 
> 
> 
> 
> 
> 



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#90563): https://edk2.groups.io/g/devel/message/90563
Mute This Topic: https://groups.io/mt/91811487/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-


Reply via email to