News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

UEFI UAsm64 ObjAsm

Started by HSE, April 09, 2022, 07:53:46 AM

Previous topic - Next topic

HSE

Hi All!!

Here some adaptation of johnsa's Unified Extensible Firmware Interface (UEFI) Example.

Code is that of Demo01B, with Triangle and Rectangle objects, but without Operative System  :biggrin: :biggrin: :biggrin:

Code (HelloOA.asm) Select

include efiOA.inc

% include @Environ(OBJASM_PATH)\Code\Macros\Model.inc   ;Include & initialize standard modules
SysSetup OOP, WIDE_STRING, EFI64;, DEBUG(CON)            ;Load OOP files and basic OS support

.data

    Handle           EFI_HANDLE 0
    SystemTablePtr   dq 0
    HelloMsg         dw 'H','e','l','l','o',' ','U','E','F','I',' ','W','o','r','l','d','!',13,10,0
    ;HelloMsg         dw 'Hello UEFI World!',13,10,0
   
    pConsole         PCONOUT 0
    pConsoleIn       PCONIN  0
    pBootServices    P_BOOT_SERVICES 0
    pRuntimeServices P_RUNTIME_SERVICES 0
   
    mapSize     UINTN  512*SIZEOF(EFI_MEMORY_DESCRIPTOR)
    descriptors EFI_MEMORY_DESCRIPTOR 512 DUP (<?>)
    mapKey      UINTN  0
    descSize    UINTN  0
    descVer     UINT32 0

include efiUtil.inc

MakeObjects Primer, Demo01

    pShape_1    $ObjPtr(Triangle)   NULL
    pShape_2    $ObjPtr(Rectangle)  NULL
   
.code

Main PROC FRAME imageHandle:EFI_HANDLE, SystemTable:PTR_EFI_SYSTEM_TABLE

    mov Handle,rcx
    mov SystemTablePtr,rdx

    mov rax,SystemTablePtr
    mov rsi,[rax].EFI_SYSTEM_TABLE.RuntimeServices
    mov pRuntimeServices,rsi
    mov rsi,[rax].EFI_SYSTEM_TABLE.BootServices
    mov pBootServices,rsi


    ;=====================================================================================
    ; The normal ASM way to make a 64bit FASTCALL.
    ;=====================================================================================
    sub rsp,20h
    lea rdx,HelloMsg
    mov rcx,SystemTablePtr
    mov rcx,[rcx + EFI_SYSTEM_TABLE_CONOUT]
    call qword ptr [rcx + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_OUTPUTSTRING]
    add rsp,20h

    ;=====================================================================================
    ; The smarter UASM way...
    ;=====================================================================================
    mov rcx,SystemTablePtr
    mov rax,[rcx].EFI_SYSTEM_TABLE.ConIn
    mov pConsoleIn,rax
    mov rax,[rcx].EFI_SYSTEM_TABLE.ConOut
    mov pConsole,rax
    invoke [rax].ConOut.OutputString, pConsole, L"Hello Smarter UEFI World!\r\n"

    mov rax, pConsole
    invoke [rax].ConOut.SetAttribute, pConsole, 017h

    ; Or if you have a list of calls to make against the same protocol/interface
    ASSUME rcx:PTR ConOut
    mov rcx,pConsole
    invoke [rcx].OutputString, pConsole, ADDR HelloMsg
    ASSUME rcx:NOTHING

   ;-----------------------------------
   ; Here !!!!!!!
   ;-----------------------------------
    mov rax, pConsole                                     ;Colors change
    invoke [rax].ConOut.SetAttribute, pConsole, 05Fh

    New Triangle                                          ;Create an new instance of Triangle
    mov pShape_1, xax                                     ;Store instance pointer

    OCall pShape_1::Triangle.Init, 10, 15                 ;Initialize Triangle
    OCall pShape_1::Shape.GetArea                         ;Invoke GetArea method of Triangle
    invoke PrintHexDWORD, eax                             ;Result = 75
    mov rcx,pConsole
    invoke [rcx].ConOut.OutputString, pConsole, L"\r\n"

    New Rectangle                                         ;Create an new instance of Rectangle
    mov pShape_2, xax                                     ;Store instance pointer
    OCall pShape_2::Rectangle.Init, 10, 15                ;Initialize Rectangle
    OCall pShape_2::Shape.GetArea                         ;Invoke GetArea method of Rectangle
    invoke PrintHexDWORD, eax                             ;Result = 150
    mov rcx,pConsole
    invoke [rcx].ConOut.OutputString, pConsole, L"\r\n"

    OCall pShape_2::Rectangle.GetPerimeter                ;Invoke GetPerimeter method
    invoke PrintHexDWORD, eax                             ;Result = 50
    mov rcx,pConsole
    invoke [rcx].ConOut.OutputString, pConsole, L"\r\n"

    Destroy pShape_2                                      ;Invoke Rectangle's Done and disposes it
    Destroy pShape_1                                      ;Invoke Triangle's Done and disposes it

    mov rax, pConsole                                     ;Colors change
    invoke [rax].ConOut.SetAttribute, pConsole, 07h

loop1:
    jmp loop1

    mov rax, pBootServices
    invoke [rax].EFI_BOOT_SERVICES.Exit, Handle, EFI_SUCCESS, 10, L"Complete\r\n"
   
    ret
Main ENDP

END Main


These are very elemental objects and calculations that only requiere to replace Win HeapAlloc and HeapFree by UEFI AllocatePool and FreePool. 

Just a little crazy how easy that can be done!

Regards, HSE
   
Note:
     I put an endless loop, to see results of calculations when booting. That can be removed if program run from UEFI Shell.
Equations in Assembly: SmplMath

Biterider

Hi HSE
Brilliant idea!  :thumbsup:
Now I fully understand what you meant here http://masm32.com/board/index.php?topic=7942.msg109335#msg109335
Since I haven't followed the UEFI thread closely (due to lack of time), I now need to install and run whatever is needed until I can build the binary.
Maybe I need help from you...

Biterider

HSE

Hi Biterider!

Quote from: Biterider on April 09, 2022, 03:35:13 PM
Now I fully understand what you meant here http://masm32.com/board/index.php?topic=7942.msg109335#msg109335
That is the idea. With UEFI you can boot from an almost regular X64 file of any size. UEFI is more like a micro OS than Bios, but perhaps will requiere to build some functions, I don't know yet.

The ideal is that somebody else with OS knowledge make that if necesary, but PC with only UEFI are very recent, and that could take time. Developers of simple BIOS OS, FreeDos for example, are not interested. 

Quote from: Biterider on April 09, 2022, 03:35:13 PM
I now need to install and run whatever is needed until I can build the binary.
There is an additional UASM package in UASM EFI/UEFI Library v1.1 with explanations.

Quote from: Biterider on April 09, 2022, 03:35:13 PM
Maybe I need help from you...
I will try :biggrin:

I'm using QEMU, but bitRAKE (also known as Rickey Bowers Jr.) help me with that. He have a package for UEFI development using fasmg in GitHub.

Regards, HSE.
Equations in Assembly: SmplMath

Biterider

Hi HSE
I'm still trying to build the dll.
I suspect I don't have the correct version installed as I can't find the original definition of RAWINTERFACE, RAWINTERFACEEND and STDFUNC. Maybe you can point me in the right direction?
From here http://masm32.com/board/index.php?topic=7942.0 I copied the macros but there is still something wrong...

I think I messed things up trying to put everything in the right order.

So far I had VirtualBox installation, which I updated now, I got the package from UASM EFI/UEFI Library v1.1 and the EDK2 from Github.

Biterider

HSE

#4
Hi Biterider!!

STDFUNC etc. are UASM internal macros, then  not use " nomlib", but you are going to have collisions. In this simple objects only you have to disable CStr macro ( I presume you see modification in model.inc and object.inc). Perhaps more easy thing will be to make that macros external, and disable all internals. Brilliant HLL things in an assembler, soon or later, are a problem. Is just a first step now. UEFI is a great static object and later can be writed includes in a more ObjAsm way.

Usually UEFI only can read FAT32. I formated an USB because my hard disks are NFTS.

You have then tools to run UEFI Shell. VirtualBox UEFI not boot from USB, you have to make a trick.
https://www.howtogeek.com/187721/how-to-boot-from-a-usb-drive-in-virtualbox/

HSE.
Equations in Assembly: SmplMath

HSE

Hi All!

Here a little update because simulation work perfectly from boot.


  • UASM things:
       I extracted internal macros (STDFUNC, etc) to file macrolib, then now -nomlib can be used in command line (for sure I messed some configuration because RAWSTRUCT work for application but for library must be STRUCT)
       I put GUID data in other file, because there is some problems of redefinition with libraries.




    include macrolib.inc
    include efiOA.inc
    include efiGUID.inc
    externdef pConsole:PCONOUT
    externdef pBootServices:P_BOOT_SERVICES

    % include @Environ(OBJASM_PATH)\Code\Macros\Model.inc   ;Include & initialize standard modules
    SysSetup OOP, WIDE_STRING, EFI64;, DEBUG(CON)            ;Load OOP files and basic OS support

    .data
        Handle           EFI_HANDLE 0
        SystemTablePtr   dq 0
        HelloMsg         dw 'H','e','l','l','o',' ','U','E','F','I',' ','W','o','r','l','d','!',13,10,0
        ;HelloMsg         dw 'Hello UEFI World!',13,10,0
       
        pConsole         PCONOUT 0
        pConsoleIn       PCONIN  0
        pBootServices    P_BOOT_SERVICES 0
        pRuntimeServices P_RUNTIME_SERVICES 0
       
        mapSize     UINTN  512*SIZEOF(EFI_MEMORY_DESCRIPTOR)
        descriptors EFI_MEMORY_DESCRIPTOR 512 DUP (<?>)
        mapKey      UINTN  0
        descSize    UINTN  0
        descVer     UINT32 0

    include efiUtil.inc
  • New ObjMemEfi:
    Very few functions now, but at some point all must be included. Mostly they are exactly the same of ObjMem64 (because conditionals in MemAlloc and FreeMem macros)
  • New OA_SetupEFI:
    used when defined new mode EFI64
  • Macros:
    In Model.inc SysSetup call OA_SetupEFI, and in Memory.inc ReAlloc have modifications but still don't tested  :biggrin:
  • Objects:
    So far Stream need a conditional modification

Like expected very little things must be modified to run from UEFI. Even if calculations are complex, from OOP point of view objects used here are like Triangle and Rectangle examples. Beside SmplMath use CPU and FPU instructions, and not OS functions.

This must be improved a little. And something is not in place because I have to link from prompt.

But first point is accomplished  :thumbsup:

Regards, HSE.

A note: I was thinking that nothing worked because emulation in qemu is  so.. slow...  :rolleyes:

Equations in Assembly: SmplMath

Biterider

Hi HSE
I've made some progress here.  :biggrin:
I was able to compile the DarylUEFI project and load the BOOT.efi created onto a fresh FAT32 formatted USB stick in the correct path.
I also created a VirtualBox machine and configured it to boot from the USB stick. Thanks for the link above.
When I started the machine I got into the "UEFI Interactive Shell" but I think this is not correct. BOOTX64.EFI should be running instead. I'm right?
Can you post your BOOTX64.EFI so I can be sure to have a working version?

Biterider

HSE

 :biggrin: :biggrin:

Hi Biterider!!

I don't know. I just copy 2 times same file. In the prompt I type "app1"  :azn:

\masm32\bin64\uasm64\uasm64 -c -win64 -nomlib -Zp8 DarylUEFI.asm
link /dll /IGNORE:4086 DarylUEFI.obj %OBJASM_PATH%\Code\Lib\64\ObjAsm\ObjMemEFI.lib
\UEFI\EFI_Toolkit_2.0\build\tools\bin\fwimage app DarylUEFI.dll DarylUEFI.EFI
copy DarylUEFI.EFI e:\EFI\BOOT\BOOTX64.EFI
copy DarylUEFI.EFI e:\App1.EFI


I think that in QEMU booting work well, but I fail to set more than 1 core  :rolleyes:.

Regards, HSE.
Equations in Assembly: SmplMath

Biterider

Hi HSE
I'm getting closer to the problem. I found that VM tries to boot all available devices before dropping into the shell. This means that the USB stick is not recognized as a boot device. Did you do anything special about this?

Biterider

HSE

Hi Biterider

Quote from: Biterider on May 30, 2022, 06:42:07 AM
This means that the USB stick is not recognized as a boot device. Did you do anything special about this?

Yes. I don't lost more time trying to boot from USB.

I just call the application from prompt.

HSE.
Equations in Assembly: SmplMath

HSE

 :biggrin: :biggrin: :biggrin:

Just a last shoot. And that work.

When you are in the shell, type "exit"

Boot maintenance manager > Boot options > Change boot order

If you don't see the hardisk, you can try Add boot option ( or other because I cliked everywhere  :biggrin:)
Equations in Assembly: SmplMath

Biterider

Hi HSE
I finally managed to launch DarylUEFI.EFI from the UEFI shell.
The trick for me was to use the Virtual Machine USB Boot program https://github.com/DavidBrenner3/VMUB/releases. With this helper I could use the stick on the host and on the VM alternately without rebooting.
Now that I've done this step, the fun can begin  :cool:

Biterider

HSE

Hi Biterider!

Quote from: Biterider on June 01, 2022, 06:20:16 AM
The trick for me was to use the Virtual Machine USB Boot program

I know existence of that trick. But it's a hack from 2013 that perhaps only work for VirtualBox of that time. I never tried that.

I pointed you to a easy current trick before, and that work. VirtualBox think that USB is a Hard Disk, and you see in Shell UEFI configuration like a Hard Disk.

Anyway, now I see the problem probably it's not related to USB :biggrin:

Multiprocess is about multicore systems, and you have only one core!!

This mean CPU2, then you have also CPU0 and CPU1 (at least 3 cores):
    mov tcb.ProcNum, 2


HSE

Equations in Assembly: SmplMath

Biterider

Hi HSE
Virtual Machine USB Boot V1.72 is from April 2018 and works perfectly with the latest VirtualBox version 6.1.
The reason I chose it is that creating the USB.vmdk didn't work for me. The VM didn't recognize a file system and what's worse, you have to detach and recreate the USB.vmdk file every time you boot your computer. The reason is that internally some UUIDs change during boot process and the previous file becomes unusable.
Maybe QEMU works differently, but I didn't have time to check it.

Biterider

HSE

Quote from: Biterider on June 01, 2022, 06:55:44 AM
Virtual Machine USB Boot V1.72 is from April 2018 and works perfectly with the latest VirtualBox version 6.1.
The reason I chose it is that creating the USB.vmdk didn't work for me. The VM didn't recognize a file system and what's worse, you have to detach and recreate the USB.vmdk file every time you boot your computer. The reason is that internally some UUIDs change during boot process and the previous file becomes unusable.

Fantastic  :thumbsup: 

Here I only need one .vmdk for each different stick. Because I'm using only 2 sticks, I use a different VM for each stick  :biggrin:

Quote from: Biterider on June 01, 2022, 06:55:44 AM
Maybe QEMU works differently, but I didn't have time to check it.

There is a problem to make a machine with more than one core in QEMU. Then I'm using VirtualBox now.

Equations in Assembly: SmplMath