Hello World (1st Version) Mac OS

This is a bit old but I'll answer it because I just learned how to do it. First there are two errors in the sample code above, they're easy to fix. On OS X 10.8 using clang this works. Clang -framework glut -framework opengl hello.cpp The above code should compile. The signature of the main function is incorrect though. In thi video I will explain How to Create First C Hello World using Xcode Mac OS XOpen Xcode an follow the stepsXcode - File - New - Project - Command Lin.

In this article, I will describe steps needed to start on with development of real UEFI applications on x86 PC, and share some practical experiences with problems doing so.I will focus on 64-bit version of UEFI, because the 32-bit version isn't much used in this area (most likely due to Microsoft decision not to support UEFI in 32-bit Vista).So, to follow some of my steps here, you'll need a 64-bit CPU (but not 64-bit OS, youcan use any 32-bit OS as well). We will finish this article with EFI Hello World application.

This article is continuation of my previous article Introduction toUEFI.Make sure to understand things described there, before reading on.

Of course, anything you try according to this article, you are doing at your own risk.

Getting the hardware

To start UEFI development, first of all you need to get a motherboard whose BIOS has UEFI support.(more precisely we should probably say 'whose firmware has UEFI support', but I will use this form).Finding whether particular BIOS has UEFI support often turns out to be quite complicated task.Motherboard manufacturers license BIOS from other companies, usually from AMI (Aptio, AMIBIOS), Phoenix (SecureCore, TrustedCore, AwardCore) or Insyde (InsydeH20). Forget about determining UEFI support just by end-user stats you see in most shops. Since UEFI support is still only in somewhatexperimental state, in many cases it isn't even listed in motherboard technical specification. In such case you are left to googling and asking on forums, where you often get only internal brand name that is often hard to match with end-user product designation.

One trick that I found out to work for Intel boards (but it may very well work for other boards as well) is to look at BIOS Update Release Notes, e. g. the document which lists changes and fixes of BIOS. If board has UEFI support, you will probably find UEFImentioned there (and only there in case of Intel).

In short, determining UEFI support is much harder than it may seem. Some machines that have this technology are listed here.I use Intel DG33BU board (it was marketed as Intel DG33BUC for some reason).

You will also need some place to boot from. In theory just USB pen should be enough, but inpractice none of 4 brands I tried worked with my board's UEFI implementation. So you may have to use harddrive. I strongly suggest IDE drive, because SATA drives may need some tweaking ofBIOS settings, or they may not work at all. Like the USB pens, USB keyboard might be a problemtoo. I wouldn't fear this that much, but if you can use PS/2 keyboard, do so.

Getting the software

To go on with UEFI development, you will need two developmentpackages: EFI Development Kit (EDK) andEFI Toolkit.

First package, the EFI Development Kit contains the TianoCore (public part of reference UEFI implementation by Intel) source code, along with many examples and binaries of EFI Shell (we'll talk about this later), all ready to be built with nice make system. It even can be built into a Win32 UEFI emulator for more convinient development and testing, but I won't cover that here. I also won't demonstrate usage of EDK build system in this article. Even though it might be a good idea for real world project, I want to give you bit more insight about what goes 'under the hood' here.

Second package, the EFI Toolkit is set of extra UEFI applications like FTP client, Python port, text editor, etc. Strictly speaking, we don't really need this, but it has a set of C headers that is somewhat easier to use than those of EDK (unless you take advantage of EDK build system for your project). However, note that it doesn't contain all headers yet - you will quickly run into this problem if you try some real development with it.

Along with headers, you also will need documentation of the UEFI interface. That can be downloadedafter filling simple form at http://www.uefi.org/specs.This is the official UEFI specification.

Except for UEFI specification, there is also another document called Platform Initialization Specification. This describes implementation of UEFI initialization stages (before drivers areloaded and applications can be executed), and more importantly for us, it also describes interfaceof routines used to implement UEFI. We can understand this Platform Initialization Specification asdescription of Tiano UEFI implementation. It provides more lowlevel control than UEFI, in cases when such control is needed. Strictly speaking, someone may implement UEFI Specification without implementing anything from Platform Initialization Specification, but that's not very likelyto happen in real world.

Last but not least, you will need 64-bit C compiler. I suggest Microsoft Visual C++, whose 64-bit version is freely available in Windows DDK. You can get it here.

Booting into EFI Shell

Up to this point, you may have lacked any visual idea about UEFI. It was just a programatic interface,after all. Purpose of this chapter would be to overcome this, by booting the so-called EFI Shell. EFI shell is much like any other shell you know: you have a command line, through which you can entercommands to browse disk, run applications, configure system, etc. Only difference is that EFI shell is only built using UEFI services, and as such it doesn't require any operating system to run. Working in EFI shell feels much like working in some very simple operating system. From this shell you will also run your applications (later in this article).

Actual steps of booting EFI shell might vary a lot among different BIOS brands. Some BIOSes (mostlyon MACs where EFI is the primary standard) have extra options for specifying file to boot, or caneven have EFI shell built-in inside ROM. However, I only have experience with non-MAC Intel UEFI implementation,that only seems to support the very minimum of features required to install EFI versions of Windows. Microsoft requirementson UEFI implementation, among other things, specify that UEFI boot loader must use fixed path to fileto boot, and if it can't boot UEFI for some reason, it must silently switch to default boot. Thatcauses lot of headache when your UEFI doesn't boot as it should, and you must find out what theproblem is without any information from loader.

For 64-bit UEFI implementations, the path to file that is booted isEFIBOOTBOOTX64.EFI. UEFIboot loader searches all filesystems it can access for this file, and when it finds it, it is executed. As I already said, if the file isn't found, booting continues with legacy BIOS. UEFI boot loader can read MBR or GPT partition tables, and can only read FAT32 partitions. This includes USB drives, so it is possible to boot EFI shell from FAT32-formatted USB pen. Unfortunately, in my tests 3 of 4 USB pens didn't work, and the 4th stopped working too after BIOS update. I had similar problemwith one of two SATA drives not working with UEFI. Therefore, I strongly suggest to use IDE drive, if you have any problems. If you already have at least one FAT32 partition on your drive, you can use it, otherwise you need to create fresh new one.

Now you need to copy binary of EFI shell to that partition. You can find 64-bit binary of EFI shellin EFI Development Kit: {EDK}OtherMaintainedApplicationUefiShellbinx64Shell_full.efi. Copyit to your FAT32 partition as EFIBOOTBOOTX64.EFI.

Now reboot, and enter into BIOS settings. In the Boottab, you should see an UEFI Boot option,enable it. If everything is allright (likely not), now after reboot you should end up in theEFI Shell. If you did, congratulations. If you didn't, and instead your regular OS booted as usual,it most likely means that UEFI boot manager wasn't able to access the drive.

First try to enter Boot Menu during BIOS screen (F10 on my machine). If the EFI Shell on FAT32 partition was detected, but didn't boot, you will see it as one of option (in my case [Internal EFI Shell--Harddrive]). If you see it, just run it. This might possibly happen if you already have some EFI operating system installed, and it has written itself as default EFI boot entry to NVRAM.

If you don't see EFI Shell in the Boot Menu, it means UEFI Boot Loader wasn't able to find any FAT32 drive with EFIBOOTBOOTX64.EFI. If you are trying to boot EFI shell from USB key, try tweakingUSB emulation settings in BIOS. Same applies to SATA disks and SATA/IDE settings. If none of settingswork, or your machine failed to boot from IDE drive, I can't help you any more than to doublecheckeverything I wrote so far (especially typos in path to EFI shell).

If you have some experience with booting EFI shell not covered in thischapter, please drop me amessage, so I can update this article.

Building an UEFI application

So, we are in EFI shell. That means we can finally test any (64-bit) EFI application we write. Time to start writing one. We will of course write and compile applications in normal operating system,not in EFI shell.

EFI application or driver is just a plain Windows PE DLL file, just with different subsystem valuein header. There are 3 new values: EFI application = 10, EFI boot service driver = 11, efi runtime driver = 12 (numbers are decimal). Question how to set subsystem will be answered later, for nowlet's focus on the DLL file.

EFI PE application doesn't have any fancies we have in Windows PEs, like symbol tables, exports, static exception handling data, etc. It does not even have imports - all you will ever need in EFI application ispassed as argument to entry point function. Only thing needed apart from data and code are relocations.So, this is simplest EFI application:

Compiling it with MS Visual C (supply your own path to EFI toolkit):

Here we set path to common EFI headers, and to platform-specific EFIheaders. The /c switch disables linking (we will link separately for better readability), and /Zl disables dependency on defaultlibc libraries.

Linking:

World

The /entry:main overrides default libc entry point to ourmain() function. The /dll forces creation of relocations. And the IGNORE:4086 disables warningLNK4086, that is caused by nonstandard main() arguments.

Now we have windows DLL, we just need to change PE subsystem value to EFI. For that, EFI Toolkit containssimple (buggy) utility that changes subsystem to one of 3 EFI values. We find this utility inEFI_Toolkitbuildtoolsbinfwimage.exe. To set subsystem to EFI app, we'll use it like this:

Produced file hello.efi should now be functional empty EFI application. We just need to copy it toour FAT32 partition, reboot to EFI shell, and test it:

If we don't get any error message, application worked.

UEFI Programming

Now we finally can get deeper into UEFI programming. Your main source for this information should bethe UEFI specification, I will only sum up most basic points.

First of all, we should know something about environemnt of UEFI applications. I will describe onlyenvironment of 64-bit x86 UEFI here (other to be found in UEFI specification).

UEFI runs in uniprocessor flat 64-bit long mode. Usually UEFI runs with memory mapping disabled (physical RAM address = virtual RAM address), but since 64-bit x86 mode requires mapping to be enabled, UEFI maps entire memory so that virtual address is same as physical (i. e. mapping is transparent). Calling convention is usual 64-bit fastcall (first4 arguments in RCX, RDX, R8,R9 with space reserved on stack; rest of arguments passedby stack; RAX, R10, R11 andXMM0-XMM5 notpreserved by called function), so you don't need to worry about special compiler settings. Notable featureof EFI is that for every supported architecture, it defines exact binary interface (ABI).

Now let's look at how our application interacts with UEFI services. First, UEFI provides set of services, called Boot Services. These are available to EFI drivers,applications, and to OS boot loader during boot. At some point during OS booting, OS loader candecide to drop them, and after that point those services become unavailable. There is also a littlenumber of services that always remain available, called 'Runtime Services'. Apart from these twosets of services, all that UEFI offers is available through so-called protocols. Protocol is verymuch like a class in object oriented programming. UEFI defines set of protocols itself (for exampleprotocols handling USB, filesystem, compression, network, …), and application can define itsown protocols (hence the 'Extensible' in 'Unified Extensible Firmware Interface'). Protocols are identified by GUID (Global Unique Identifier, google it if you don't know what it is). Only very fewprotocols are mandatory in UEFI specification, and all the rest may or may not be implemented inparticular firmware. If protocol isn't implemented in firmware, you can load a driver that implements it, or even write such driver yourself.

Now let's look at how to access these services. As I already explained, all you ever need is passed as argument to entry point function. Prototype of entry point function looks like this:

First argument is handle of our process, nothing extra to say about it. Second is pointer to EFI_SYSTEM_TABLE, the top-level EFI structure, which keeps references to everything there is:boot/runtime services, drivers, protocol implementations, memory maps, etc. It is good ideato always save both these arguments in a global variable, so you can access them from anywherein source code. You can find detailed description of EFI System Table in UEFI Specification chapter 4 - EFI System Table. Its C definition looks like this:

Here we see references to boot and runtime services, three standard I/O handles (as implementationsof SIMPLE_TEXT_OUTPUT and SIMPLE_INPUTprotocols), and pointer to ConfigurationTable. Configuration Table holds references to all otherprotocol implementations currently active in system.

First we will show example of using Boot Service. The EFI_BOOT_SERVICES is just a structure that holds pointers to functions described in UEFI Specification chapter 6: Services - Boot Services. For nowwe will use only simple Exit() function, that terminates current EFI application immediately.

Now, we will show simple Hello World application, using the ConOut implementation of SIMPLE_TEXT_OUTPUTprotocol. This protocol is described in UEFI Specification chapter 11.4 - Simple Text Output Protocol.Its C header looks like this:

We are of course interested in OutputString() function, whose prototype is:

Note that UEFI uses Unicode strings only, hence the CHAR16 *String. This pointer meaning is exactly same as in any object oriented programming. With this info, we should be ableto write Hello World app easily:

Also note that UEFI uses CRLF line terminators (rn) instead of just LF (n), and when weuse native EFI functions, there is no layer which reinterprets LF to CRLF. Normally, applications use additional library called EFILIB which does the LF->CRLF transform.

UEFI Programming with FASM

As an extra, I will also demonstrate same Hello World example inassembly (using FASM, thatcurrently has experimental UEFI support since version 1.67.28):

First we need some to create simple UEFI headers (efi.inc):

And here is the assembly code itself (hello.asm):

Compile and link it with fasm.exe hello_world.asm.

That's all for now, hope you enjoyed yourselves.

Comments

Continue to discussion board.

You can contact the author using e-mail vid@x86asm.net.

Visit author's home page.

Revisions

(dates format correspond to ISO 8601)

Java and the Mac OS X Terminal


This page is obsolete.


This document instructs you on how to use the Mac OS X Terminal with Java.

Java

You will use the Java compiler javac to compile your Java programs andthe Java interpreter java to run them.To verify that Apple's implementation of Java 2 Standard Edition (Java SE 6) isalready installed:

  • Run Software Update.
  • Run Applications/Utilities/Java/Java Preferencesand verify that the Java SE 6 - 64-bit entry is checked andfirst in the list; if not, drag to change the preferred order.
Command-line interface

You will type commands in an application called the Terminal.

  • Open a terminal window. You can find this underGo -> Applications -> Utilities. Drag the Terminal to your dock sinceyou will be using it frequently.
  • You should now have a Terminal window somewhere on the screen.It will have a prompt that looks something like:
  • To check that you are running the right version of Java, typethe commands in boldface below. You should see something similar to the information printed below. The importantpart is that it says 1.6 or 1.5 (and not 1.4).
    Then type
  • Since you will be using the Terminal frequently, you may want tocustomize the default window settings (e.g., Monaco 13pt font with antialiasing).
Compile the program

You will use the javac command to convert your Java program into a form moreamenable for execution on a computer.

  • From the Terminal, navigate to the directory containing your .javafiles, say ~wayne/introcs/hello, by typing the cd commandbelow.
  • Assuming the file, say HelloWorld.java is in the currentworking directory, type the javac command below to compile it.
    If everything went well, you should see no error messages.
Execute the program

You will use the java command to execute your program.

  • From the Terminal, type the java command below.If all goes well, you should see the output of the program -Hello, World.

Hello World (1st Version) Mac Os Download

Input and Output

Hello World (1st Version) Mac Os Pro

If your program gets stuck in an infinite loop, type Ctrl-c to break out.

If you are entering input from the keyboard, you can signifyto your program that there is no more data by typingCtrl-d for EOF (end of file).You should type this character on its own line.

Troubleshooting

When I try to run java I get: Exception in thread 'main' java.lang.NoClassDefFoundError.First, be sure that HelloWorld.class is in the current directory.Be sure to type java HelloWorld without a trailing .classor .java.If this was not your problem, it's possiblethat your CLASSPATH was set by some other program so that it no longerincludes the current working directory.Try running your program with the command line

If this works, your classpath is set incorrectly.

I get the error 'class file has wrong version 50.0, should be 49.0' when I compilefrom the Terminal. What does this mean?It's probably because DrJava is configured to use Java 6.0 and and your Terminal is configured to use Java 5.0.To change the default version of Java in your Terminal, launchJava Preferencest. Drag the Java SE 6 - 64-bit entryto appear first.

Hello World (1st Version) Mac Os Catalina

How do I get the menu to display at the topof the screen instead of at the top of the frame?Execute with java -Dapple.laf.useScreenMenuBar=true

Hello World (1st Version) Mac Os 11

Where can I learn more about the command line?Here is a short tutorial on thecommand-line.