wtorek, 1 listopada 2016

openSUSE Tumbleweed - grub2 installed in non-EFI mode

Last time after I've installed openSUSE Tumbleweed, I've got incorrect grub2 installation (but system instalation was successful). Instead of using EFI my grub2 was configured to run in the classic mode. After reboot I was able to see only the grub2 command line.

Here is the solution:

First we need to find our grub config file. We can do it using:
 > search.file /boot/grub2/grub.cfg
We should get something like:
 (hd1,gpt6)
Now load that config:
 > configfile (hd1,gpt6)/boot/grub2/grub.cfg
The grub menu should appear. Unfortunately entries were incorrect because of using e.g. "linux" command instead of "linuxefi". We have to change that, so press "e" to edit your entry. Next, change "linux" to "linuxefi" and "initrd" to "initrdefi".
To boot press F10.
After your OS is loaded open YaST, then go to Bootloader settings and change mode to "GRUB2 EFI". Done!

środa, 14 września 2016

LibreOffice conference 2016 - Brno


This year again I had the pleasure to attend in the annual LibreOffice conference. This time it was organized in Brno, Czech Republic on September 7-9th 2016.

The conference was very well organized. The conference venue was located in the modern campus of the Faculty of Information Technology at the Brno University of Technology. Every day we listened talks and participated in events on evenings. It was a good opportunity to meet my mentors and other GSoC students. One of the best things is that you can find out who is behind well known IRC nick :)

First day started with opening session and presentation of the state of the project. That day we also took part in HackNight - hacking together in the Red Hat office. My short talk was on the last day of the conference. There was a GSoC panel where we were able to present our projects. At the end we went sightseeing Brno.

I would like to thank sponsors, The Document Foundation and all organizers for a great event.

We also found out where will be organized next meeting.


See you next year in Rome!

piątek, 19 sierpnia 2016

GSoC 2016 - Infrastructure for defining toolbars via .ui (Glade) files - Final report

My all commits can be found here: https://cgit.freedesktop.org/libreoffice/core/log/?qt=author&q=eszkadev%40gmail.com

Tasks from my proposal


Done:
  • Loading of different toolbar definitions in the Writer, Calc and Impress
  • NotebookBar and Classic mode switching
  • Mechanism to show/hide widgets depending on the context
  • Priorities for widgets to allow dynamic hiding according to screen size
  • Improved look of various widgets for their presentation in the toolbar

Not finished:
  • Mechanism to add new tabs for the extensions
  • Mechanism to customize the toolbar

Main changes


  • Controls converted to be used outside sidebar:
  • Possibility to change icon size in the Sidebar and Notebookbar [commit] [commit]

  • Sidebar panels converted to single widgets:
  • Container with widget priorities [commit]
    • widget groups are collapsed when there is no enough space, user can access them from a dropdown menu


  • Multiple Notebookbar implementations [commit]
    • user can switch to other view using menubar

  • Toolbar modes - tdf#101249 [commit]
    • User can switch between different modes: default, single toolbar, sidebar and notebookbar
  • Created custom widgets for better look:
    • SmallButton - button with reduced width [commit]
    • BigToolBox - container for large buttons with dropdown menu [commit]


    • NotebookbarToolBox - container with possibility to switch icon size to use in the Notebookbar


    • NotebookbarTabControl - TabControl with context dependent tabs and the file popup menu

niedziela, 10 lipca 2016

The environment to program AVR microcontrollers on Windows

I've tested a lot of tools which can be used to develop systems based on AVRs and finally found something ideal for me. My setup:

WinAVR is a pack of needed apps: compiler (avr-gcc) and programming tool (avrdude). We should install it first. As an IDE I use Eclipse. The advantage of Eclipse is that I can share the same project on Windows and Linux. It supports my low-cost programmer - USBasp and I can easily change fuse bits clicking in the GUI:



To intall AVR plugin follow this tutorial.
On newer versions of Windows you can met problem with avr-gcc (error 0xc0000142):



To fix this issue you have to download fixed dll and copy to (WinAVR PATH)\utils\bin.

The last step is to add programmer in Eclipse to the AVR properties. To create new AVR project click New Project > C Project > AVR Cross Target Application > Empty Project and then set your MCU type, frequency etc.

To install USBasp in Windows the driver is needed: http://zadig.akeo.ie/. You have to choose "libusb-win32" in the driver field.

niedziela, 3 lipca 2016

Android - how to communicate with PC using serial port over bluetooth

One time I needed to simulate a device which communicates with PC over bluetooth. I thought that I can use my smartphone with Android because this is faster way than creating new device using microcontroler and bluetooth module. I needed only my phone, Android Studio and a USB cable. I used code from Bluetooth Android Guide.
The most important line is:
 tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
Name parameter can be any value, but in the UUID you should pass correct value if you want to use serial port. This value is:
UUID.fromString(00001101-0000-1000-8000-00805F9B34FB)

Where base UUID is "00000000-0000-1000-8000-00805F9B34FB" and 0x1101 is the UUID of "SerialPort" service class. You can check service classes here.
After uploading application to the device and running application, you have to pair your phone with a PC. Sometimes COM port (on Windows) is binded just after pairing, but often you must do it manually. To do this you have to open bluetooth settings.


Then go to the "COM Ports" tab and click "Add". Select outgoing type and also your device from listbox. You should also see your application name below.



Click OK and you should get your COM port number.

sobota, 2 lipca 2016

Windows 10

For many years my main operating system is Linux (currently openSUSE) but I also have installed Windows because sometimes I have to run or develop some native Windows apps. Some time ago I updated my Windows 8 to newer version - Windows 10.

Update was finished without any problems and after 3-4 hours I saw my new desktop. I'm rather a user who keeps opened a lot of windows simultanusely and for me the most important new feature is the support of multiple desktops:


I was using this in my Gnome desktop for a long time and one thing what is missing for me in the Windows implementation is a possibility to move window between desktops using a shortcut (or I missed this in the shortcut list). Nevertheless, the work on Windows isn't as much painful for me finally.

I also noticed one regression in sense of usability. Developers changed power management popup (shown after click on the battery tray icon) and now it is less functional:



I often switch between balanced and high performance modes, but now I can turn on/off only power-saving mode. To run high performance mode I have to click few times more (open power settings). This is the reason why I created shortcut on my desktop switching to the high performance mode:

powercfg.exe /setactive GUID

Where GUID is one from the list:

powercfg -LIST



poniedziałek, 22 lutego 2016

EDKII and QEMU - remote debugging with gdb

While working with UEFI debugger can be very helpful. I was using EDKII project to write my UEFI applications and I was testing it with QEMU. I added my application information file to the OvmfPkg module information and this let me to running my program using existing script.
To build OvmfPkg and run QEMU run (in the OvmfPkg folder):
 ./build.sh -A IA32 qemu -s -monitor stdio -debugcon file:debug.log -global isa-debugcon.iobase=0x402  
After start debug.log file will be created where you can read output from UEFI.
We need to know where your application will be loaded (memory address). Run your application in QEMU:
 Shell> fs0:  
 fs0:\> MyApp.efi  
Open debug.log file (in the EDKII directory), and find line with name of your loaded application. You should get something like this:
 Loading driver at 0x00006B75000 EntryPoint=0x00006B75220 MyApp.efi  
And this is our address:
 EntryPoint=0x00006B75220  
Now open second terminal, open directory with your application's debugging symbols and efi file (for me: Build/OvmfIa32/DEBUG_GCC48/IA32/MyApp.debug) and run gdb:
 gdb --tui  
We need to know where particular sections are located. Load efi file and enter info files:
 (gdb) file MyApp.efi  
 Reading symbols from MyApp.efi...(no debugging symbols found)...done.  
 (gdb) info files  
 Symbols from ".../edk2/Build/OvmfIa32/DEBUG_GCC48/IA32/MyApp.efi".  
 Local exec file:  
     `.../Build/OvmfIa32/DEBUG_GCC48/IA32/MyApp.efi', file type pei-i386.  
     Entry point: 0x220  
     0x00000220 - 0x00003a40 is .text  
     0x00003a40 - 0x00004320 is .data  
     0x00004320 - 0x00004520 is .reloc  
We need to calculate our addresses for text and data section. Application is loaded under 0x00006B75220 (entry point) and we know text and data offsets.
text = 0x06B75220
data = 0x06B75220 + 0x00003a40 = 0x06B78C60

Now unload efi file:
 (gdb) file  
 No executable file now.  
 No symbol file now.  
Load symbols:
 (gdb) add-symbol-file MyApp.debug 0x06B75220 -s .data 0x06B78C60
add symbol table from file "MyApp.debug" at
        .text_addr = 0x6b75220
        .data_addr = 0x6b78c60
(y or n) y
Reading symbols from MyApp.debug...done.
You can add some breakpoints, for example:
 break UefiMain  
And attach debugger to the QEMU:
 target remote localhost:1234  
And run QEMU:
 ./build.sh -A IA32 qemu -s -monitor stdio -debugcon file:debug.log -global isa-debugcon.iobase=0x402  
Machine will be paused, type "continue", load your application. Done!



Links:
http://osdevnotes.blogspot.com/2011/05/using-gdb-to-debug-uefi.html
http://wiki.osdev.org/Debugging_UEFI_applications_with_GDB
http://comments.gmane.org/gmane.comp.bios.tianocore.devel/6777

Samba 3 with LDAP as a Primary Domain Controller

In this tutorial I will show how to configure samba 3 as a PDC with LDAP support. It will be possible also to use domain users on the server machine. I was using minimal Debian 8, openLDAP 2.4 (from repositories) and samba 3.6 (compiled from sources). My hostname is ldapserv and domain domain.edu

LDAP


First install LDAP from repository:
 apt-get install slapd ldap-utils  

Then edit /etc/ldap/ldap.conf file and set your domain base and URI:
 BASE   dc=domain,dc=edu  
 URI    ldap://127.0.0.1/  

You can check if it is working with:
 ldapsearch -x  

You should get information about domain and admin.
Now create temporary file (temp.ldif) with this content:
 dn: ou=People,dc=domena,dc=edu  
 ou: People  
 objectClass: organizationalUnit  
 dn: ou=Group,dc=domena,dc=edu  
 ou: Group  
 objectClass: organizationalUnit  
This describes new nodes in our LDAP tree which will be used for our users and groups.
Add these nodes to the tree:
 ldapadd -c -x -D cn=admin,dc=domain,dc=edu -W -f temp.ldif  
cn=admin,dc=domain,dc=edu this is my LDAP admin

Restart slapd:
 systemctl restart slapd.service  

Now we can create and add new user. Open new temporary file (john.ldif):
 dn: cn=john,ou=group,dc=domain,dc=edu  
 cn: john  
 gidNumber: 20000  
 objectClass: top  
 objectClass: posixGroup  
 dn: uid=john,ou=people,dc=domain,dc=edu  
 uid: john  
 uidNumber: 20000  
 gidNumber: 20000  
 cn: john  
 sn: john  
 objectClass: top  
 objectClass: person  
 objectClass: posixAccount  
 objectClass: shadowAccount  
 loginShell: /bin/bash  
 homeDirectory: /home/john  

Add john.ldif:
 ldapadd -c -x -D cn=admin,dc=domain,dc=edu -W -f john.ldif  

Set the password for john:
 ldappasswd -x -D cn=admin,dc=domain,dc=edu -W -S uid=john,ou=people,dc=domain,dc=edu  

NSS


When you enter command "id john", system couldn't find our user. We can make it possible.
 apt-get install libnss-ldap nscd  

Edit /etc/libnss-ldap.conf:
 BASE   dc=domain,dc=edu  
 URI    ldap://127.0.0.1/  

Edit /etc/nsswitch.conf and change these lines to:
 passwd:     files ldap  
 group:      files ldap  

Run:
 systemctl stop nscd.service  

And check again "id john", now you should see information about your user.

PAM


In this moment our OS know user "john", but it is impossible to log in. We must provide information about passwords for PAM. Install ldap support:
 apt­-get install libpam­ldap  

Again enter your ldap base and uri in this file:
 nano /etc/pam_ldap.conf  

Then write to files (and delete previous content):
/etc/pam.d/common­account:
 account sufficient      pam_unix.so  
 account required        pam_ldap.so  

/etc/pam.d/common­auth:
 auth [success=1 default=ignore] pam_unix.so nullok_secure  
 auth required pam_ldap.so use_first_pass  
 auth required pam_permit.so    

/etc/pam.d/common­session:
 session required        pam_unix.so  
 session required        pam_mkhomedir.so skel=/etc/skel/ umask=0022   

Now test settings (on second terminal, without restarting, because you can lost your system).

SAMBA


We will create domain controller with samba. I will be using Windows 7 clients so samba version mus be >= 3.3.
Download and extract samba sources:
 wget https://download.samba.org/pub/samba/samba­3.6.25.tar.gz  
 tar ­zxvf samba­3.6.25.tar.gz  
 cd samba­3.6.25/source3  

Install required libraries:
 apt­get install gcc make libldap2­dev libkrb5­dev libpam0g­dev  

Configure and compile samba (with LDAP support, install dir: ​/usr/local/samba):
 ./configure ­­prefix=/usr/local/samba/ ­­--with­-ldap ­­--with­-ads ­­--with­-pam ­­--disable­-cups  
 make  
 make install    

Add samba schema to the LDAP schema directory:
 cd ..  
 cp examples/LDAP/samba.schema /etc/ldap/schema/samba.schema   

Now we will add this schema to the LDAP configuration. To do this using LDAP 2.4 we must create ldif file. Create file schema_convert.conf:
 cd ~/  
 nano schema_convert.conf  

And pase this content:
 include /etc/ldap/schema/core.schema  
 include /etc/ldap/schema/collective.schema  
 include /etc/ldap/schema/corba.schema  
 include /etc/ldap/schema/cosine.schema  
 include /etc/ldap/schema/duaconf.schema  
 include /etc/ldap/schema/dyngroup.schema  
 include /etc/ldap/schema/inetorgperson.schema  
 include /etc/ldap/schema/java.schema  
 include /etc/ldap/schema/misc.schema  
 include /etc/ldap/schema/nis.schema  
 include /etc/ldap/schema/openldap.schema  
 include /etc/ldap/schema/ppolicy.schema  
 include /etc/ldap/schema/samba.schema    

Generate cn=samba.ldif file using slapcat:
 mkdir ­-p ldif_output  
 slapcat ­-f ~/schema_convert.conf ­-F ~/ldif_output ­-n0 ­-s "cn={12}samba,cn=schema,cn=config"  > ~/cn=samba.ldif  

Edit file:
 nano cn=samba.ldif    

Delete {13} from lines 1 and 3:
 dn: cn=samba,cn=schema,cn=config  
 objectClass: olcSchemaConfig  
 cn: samba    

And delete this lines (from the end of file):
 structuralObjectClass: olcSchemaConfig  
 entryUUID: bd8a7a82­3cb8­102f­8d5f­070b4e5d16f8  
 creatorsName: cn=config  
 createTimestamp: 20100815125953Z   
 entryCSN: 20100815125953.198505Z#000000#000#000000  
 modifiersName: cn=config  
 modifyTimestamp: 20100815125953Z    

Add ldif file to the LDAP configuration:
 ldapadd ­-Y EXTERNAL ­-H ldapi:/// ­-f ~/cn=samba.ldif   

Restart ldap:
 systemctl restart slapd    

Create samba config file:
 nano /usr/local/samba/lib/smb.conf    

And paste:
 [global]  
 ldap admin dn = "cn=admin,dc=domain,dc=edu"  
 passdb backend = ldapsam:ldap://127.0.0.1:389  
 ldap ssl = off  
 ldap suffix = "dc=domain,dc=edu"  
 ldap passwd sync = yes  
 ldap group suffix = ou=Group  
 ldap user suffix = ou=People  
 workgroup = DOMAIN.EDU  
 netbios name = LDAPSERV  
 local master = yes  add machine script = /usr/sin/useradd ­-d \  /dev/null ­-g 200 ­-s /sbin/nologin ­-M %u  
 security = user  
 logon drive = H:  
 domain master = yes  
 domain logons = yes  
 preferred master = yes  
 wins support = yes  
 log level = 2  
 log file = /usr/local/samba/logs  
 [homes]  
 comment = Home dirs  
 path = /home/%u  
 read only = no  
 create mode = 0750  
 browseable = yes  
 [netlogon]  
 path = /usr/local/samba/netlogon  
 guest ok = yes  
 browseable = no  
 [profiles]  
 path = /usr/local/samba/profiles  
 writeable = no  
 guest ok = yes  
 browseable = yes  
 create mode = 0700   

Create directories and group for machines:
 mkdir /usr/local/samba/profiles  
 mkdir /usr/local/samba/netlogon  
 groupadd ­-g 200 machine    

Test config:
 /usr/local/samba/bin/testparm    

Change samba admin password:
 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/samba/lib  
 /usr/local/samba/bin/smbpasswd ­-W    

We need samba tools to create LDAP nodes:
 cpan  
 cpan> install Net::LDAP  
 cpan> install Crypt::SmbHash  
 cpan> install Digest::SHA1  
 cd ~/  
 wget http://download.gna.org/smbldap­tools/sources/0.9.9/smbldap­tools­0.9.9.tar.gz  
 tar xvfz smbldap­tools­0.9.9.tar.gz  
 cd smbldap­tools­0.9.9  
 ./configure --­­with­-samba­-sysconfdir=/usr/local/samba/lib  ­--with­-samba­-bindir=/usr/local/samba/bin --sysconfdir=/etc/samba  
 make && make install    

Copy config files:
 cp ­-pr smbldap.conf /etc/samba/smbldap­tools/smbldap.conf  
 cp ­-pr smbldap_bind.conf /etc/samba/smbldap­tools/smbldap_bind.conf   

Get domain SID number:
 export PATH=$PATH:/usr/local/samba/bin  
 net getlocalsid   

Edit /etc/samba/smbldap­tools/smbldap.conf and change lines:
 SID=<YOUR SID>  
 sambaDomain="DOMAIN.EDU"  
 masterLDAP="ldap://127.0.0.1/"  
 ldapTLS="0"  
 verify="require"  
 suffix="dc=domain,dc=edu"  
 usersdn="ou=People,${suffix}"  
 groupsdn="ou=Group,${suffix}"  
 userHome="/home/%U"  
 userSmbHome="\\LDAPSERV\%U"  
 userProfile="\\LDAPSERV\profiles\%U"   

Edit /etc/samba/smbldap­tools/smbldap_bind.conf:
 masterDN="cn=admin,dc=domain,dc=edu"  
 masterPw="<ldap admin password>"    

Run:
 smbldap­-populate  

Add library path:
 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/samba/lib    

Restart samba:
 killall smbd  
 killall nmbd  
 /usr/local/samba/sbin/smbd  
 /usr/local/samba/sbin/nmbd    

You can check domain state:
 /usr/local/samba/bin/findsmb    

Add user for our domain:
 useradd DOMAIN.EDU$  
 /usr/local/samba/bin/smbpasswd ­-a -­i DOMAIN.EDU  ​ (without $)    

Add users


Add user with:
 smbldap­-useradd <name>   

Then set password:
 smbpasswd -­a <name>  
Now you can join to this domain with Windows 7 client but remember to change compatibility settings.

środa, 10 lutego 2016

Joining a Windows 7 client to a samba 3 domain controller

When you want to join a domain served by a samba 3 domain controller using Windows 7, you probably will get some errors. To achieve this you must turn on some compatibility options in the Windows register.

1. Run regedit
2. Go to: HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\LanManWorkstation\Parameters
3. Create (or modify) this parameters: "DNSNameResolutionRequired" = DWORD(0) and "DomainCompatibilityMode" = DWORD(1)


4. Join the domain.

niedziela, 7 lutego 2016

UEFI programming using pure assembler (32bit mode)

I was writing some small UEFI applications. UEFI is a powerful BIOS successor, which introduces a lot of features. Unfortunately not every implementations on real hardware supports all these things. I neeed only basic functionality like writing some text for test purposes and wrote small test programs using pure assembler.

In the internet you can easily find an asm code for 64 bit architecture but not for 32 bit. I shared my translated code https://github.com/eszkadev/UEFI-32bit-asm-examples

Most important file is efi.inc which describes EFI structures:
 ;  
 ; EFI.inc  
 ; Based on: http://wiki.osdev.org/Uefi.inc  
 ; 2015 Szymon Kłos  
 ;  
   
 struc int8 {  
  . db ?  
 }  
   
 struc int16 {  
  align 2  
  . dw ?  
 }  
   
 struc int32 {  
  align 4  
  . dd ?  
 }  
   
 struc int64 {  
  align 8  
  . dq ?  
 }  
   
 struc intn {  
  align 4  
  . dd ?  
 }  
   
 struc dptr {  
  align 4  
  . dd ?  
 }  
   
  ; symbols  
   
 EFI_SUCCESS                       equ    0  
   
 EFI_SYSTEM_TABLE_SIGNATURE        equ    20494249h  
 EFI_SYSTEM_TABLE_SIGNATURE2       equ    54535953h  
 EFI_RUNTIME_SERVICES_SIGNATURE    equ    544e5552h  
 EFI_RUNTIME_SERVICES_SIGNATURE2   equ    56524553h  
   
  ; helper macro for definition of relative structure member offsets  
   
 macro struct name  
 {  
  virtual at 0  
   name name  
  end virtual  
 }  
   
  ; structures  
   
 struc EFI_TABLE_HEADER {  
  .Signature                  int64  
  .Revision                   int32  
  .HeaderSize                 int32  
  .CRC32                      int32  
  .Reserved                   int32  
 }  
 struct EFI_TABLE_HEADER  
   
 struc EFI_SYSTEM_TABLE {  
  .Hdr                        EFI_TABLE_HEADER  
  .FirmwareVendor             dptr  
  .FirmwareRevision           int32  
  .ConsoleInHandle            dptr  
  .ConIn                      dptr  
  .ConsoleOutHandle           dptr  
  .ConOut                     dptr  
  .StandardErrorHandle        dptr  
  .StdErr                     dptr  
  .RuntimeServices            dptr  
  .BootServices               dptr  
  .NumberOfTableEntries       intn  
  .ConfigurationTable         dptr  
 }  
 struct EFI_SYSTEM_TABLE  
   
 struc SIMPLE_TEXT_OUTPUT_INTERFACE {  
  .Reset                      dptr  
  .OutputString               dptr  
  .TestString                 dptr  
  .QueryMode                  dptr  
  .SetMode                    dptr  
  .SetAttribute               dptr  
  .ClearScreen                dptr  
  .SetCursorPosition          dptr  
  .EnableCursor               dptr  
  .Mode                       dptr  
 }  
 struct SIMPLE_TEXT_OUTPUT_INTERFACE  
   
 struc EFI_SIMPLE_TEXT_INPUT_PROTOCOL {  
  .Reset                      dptr  
  .ReadKeyStroke              dptr  
  .WaitForKey                 dptr  
 }  
 struct EFI_SIMPLE_TEXT_INPUT_PROTOCOL  
   
 struc EFI_INPUT_KEY {  
  .ScanCode                   int16  
  .UnicodeChar                int16  
 }  
 struct EFI_INPUT_KEY  
   
 struc EFI_RUNTIME_SERVICES {  
  .Hdr                        EFI_TABLE_HEADER  
  .GetTime                    dptr  
  .SetTime                    dptr  
  .GetWakeUpTime              dptr  
  .SetWakeUpTime              dptr  
  .SetVirtualAddressMap       dptr  
  .ConvertPointer             dptr  
  .GetVariable                dptr  
  .GetNextVariableName        dptr  
  .SetVariable                dptr  
  .GetNextHighMonotonicCount  dptr  
  .ResetSystem                dptr  
 }  
 struct EFI_RUNTIME_SERVICES  
   
 struc EFI_TIME {  
  .Year                       int16  
  .Month                      int8  
  .Day                        int8  
  .Hour                       int8  
  .Minute                     int8  
  .Second                     int8  
  .Pad1                       int8  
  .Nanosecond                 int32  
  .TimeZone                   int16  
  .Daylight                   int8  
  .Pad2                       int8  
  .sizeof                     rb 1  
 }  
 struct EFI_TIME  

Pointer to the EFI_SYSTEM_TABLE structure is passed to your entry function. EFI uses C calling convention and you can get it from the stack:

 format pe dll efi  
 entry main  
   
 section '.text' code executable readable  
   
 include 'efi.inc'  
   
 main:  
     push ebp  
     mov ebp, esp  
   
  ; get args ( ImageHandle and SystemTable pointer )  
   
     mov ecx, [ebp+8]  
     mov [ImageHandle], ecx  
     mov edx, [ebp+12]  
     mov [SystemTable], edx  
   
  ; ... YOUR CODE  
   
     mov eax, EFI_SUCCESS  
   
     pop ebp  
     retn  
   
 section '.data' data readable writeable  
   
 ImageHandle        dd        ?  
 SystemTable        dd        ?  
   
 section '.reloc' fixups data discardable  

Simple HelloWorld: https://github.com/eszkadev/UEFI-32bit-asm-examples/blob/master/HelloWorld.asm

EFI application binary must be in a PE format. You can compile this code with fasm. Then place it on your disc and run from UEFI Shell (for example using Virtualbox).

Links:
http://wiki.osdev.org/Uefi.inc
http://x86asm.net/articles/uefi-programming-first-steps/index.html