Getting started with UEFI

Discussions on more advanced topics such as monolithic vs micro-kernels, transactional memory models, and paging vs segmentation should go here. Use this forum to expand and improve the wiki!
blm768
Member
Member
Posts: 45
Joined: Fri Jun 29, 2012 11:32 am

Re: Getting started with UEFI

Post by blm768 »

Brendan wrote: By different versions of the OpenGL library, I mean "Each version of the shared library would be tailored to a specific driver, so the interface between the userspace library and the driver would be implementor-defined.".
Oh, I see now...
Brendan wrote: The job of a device driver is to provide an abstraction layer; so that other software doesn't need to care about underlying hardware details. For example, you wouldn't force applications to care about "cylinder, head, sector" for file IO would you?
My plan was actually to provide some abstraction with the buffer. The fact that the rendering is done to a buffer rather than directly to a portion of the screen would not be exposed to the application itself; the application code would be written as normal. The window manager is responsible for compositing these buffers to form the full desktop. Only the window manager would have to deal with different versions of the library, and it could just communicate with several driver-like processes, one for each card.
For example, Application A might be rendering exclusively with Graphics Card A, and App B is using Card B, but the window manager can put App A on Card B's desktop and vice versa because neither application directly draws to the screen. The system would automatically assign each application to a card when it started and would try to keep the load balanced between cards.
It might not be the best solution, but it seems like it would be just fine for a compositing WM, which most modern OSes are using anyway. Of course, just splitting the draw calls could also work, but the downside is that for complex scenes, each card would have to process the same geometry, which might, depending on the scene, be less efficient than just passing a buffer, and some graphical effects (like deforming windows) would be difficult to implement in the window manager.

On a different note, I'm trying to work out why the firmware isn't giving me a memory map. Here's the code I'm using:

Code: Select all

//Get memory map
UINTN mapSize = 0;
EFI_MEMORY_DESCRIPTOR *memMap;
UINTN mapKey, descriptorSize;
UINT32 descriptorVersion;

//Places the correct size into mapSize
status = uefi_call_wrapper(bootServices->GetMemoryMap, 5, &mapSize, NULL, &mapKey, &descriptorSize, &descriptorVersion);
status = uefi_call_wrapper(bootServices->AllocatePages, 4, AllocateAnyPages, EfiLoaderData, (mapSize / 4096) + 1, &memMap);
if(status != EFI_SUCCESS) {
	print(L"Error: unable to allocate memory map buffer\r\n");
	return status;
}
	
//Actually get the memory map.
status = uefi_call_wrapper(bootServices->GetMemoryMap, 5, &mapSize, memMap, &mapKey, &descriptorSize, &descriptorVersion);
if(status != EFI_SUCCESS) {
	print(L"Error: unable to obtain memory map\r\n");
	if(status == EFI_BUFFER_TOO_SMALL) {
		print(L"Buffer too small\r\n");
	}
	return status;
}
The second GetMemoryMap call returns EFI_BUFFER_TOO_SMALL even if I set the amount allocated (in pages) to mapSize << 5. I'd think that would be plenty...
Is there a function to format a number as a string, or will I have to write that myself if I want to print a debug value?

I'm also having a tough time getting the EFI_LOAD_FILE_INTERFACE that I think is what I need to call LoadFile(). I'm trying this code, which is based on efilib:

Code: Select all

EFI_LOAD_FILE_INTERFACE *filesystem;
status = LibLocateProtocol(&LoadFileProtocol, &filesystem);
if(status != EFI_SUCCESS) {
	print(L"Error getting EFI_LOAD_FILE_INTERFACE\r\n");
	return status;
}
I'm wondering if I should just find the protocol "manually" (with pure UEFI calls), but figuring that out looks miserable.

Man, I'm sure asking a lot of questions...and this topic is even in the wrong section of the forums. I must look like a complete newbie. :oops:
Anyway, thanks for your help so far!
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Getting started with UEFI

Post by Brendan »

Hi,
blm768 wrote:On a different note, I'm trying to work out why the firmware isn't giving me a memory map. Here's the code I'm using:
Allocating pages for the memory map can change the size of the memory map. For this reason I think you need something like a "do { ... } while(allocated pages weren't enough);" loop.

It's probably a good idea to write some sort of "display_EFI_error()" routine too. An error message like ""Error: unable to allocate memory map buffer" doesn't tell you why EFI didn't let you allocate memory, which makes it harder to fix the problem (was the operation not supported, was there bad arguments, was there not enough free RAM, was "mapSize" dodgy because nobody checked the status of the previous "GetMemoryMap()" call, etc).
blm768 wrote:Is there a function to format a number as a string, or will I have to write that myself if I want to print a debug value?
I'd write that myself (even if there was a function provided by UEFI or efilib). ;)
blm768 wrote:I'm also having a tough time getting the EFI_LOAD_FILE_INTERFACE that I think is what I need to call LoadFile(). I'm trying this code, which is based on efilib:
I'm not too sure about the "Load File Protocol" - I used the "EFI File Protocol" (open, read, close) instead.


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
blm768
Member
Member
Posts: 45
Joined: Fri Jun 29, 2012 11:32 am

Re: Getting started with UEFI

Post by blm768 »

Brendan wrote: Allocating pages for the memory map can change the size of the memory map. For this reason I think you need something like a "do { ... } while(allocated pages weren't enough);" loop.
I'll try that. I thought that I had way more than enough free space when I set it to allocate (mapSize << 5) pages, but maybe not...hmm...
Brendan wrote: It's probably a good idea to write some sort of "display_EFI_error()" routine too. An error message like ""Error: unable to allocate memory map buffer" doesn't tell you why EFI didn't let you allocate memory, which makes it harder to fix the problem (was the operation not supported, was there bad arguments, was there not enough free RAM, was "mapSize" dodgy because nobody checked the status of the previous "GetMemoryMap()" call, etc).
Eventually...
Brendan wrote: I'm not too sure about the "Load File Protocol" - I used the "EFI File Protocol" (open, read, close) instead.
I missed that in the docs. I'll try that instead; it looks simpler.
blm768
Member
Member
Posts: 45
Joined: Fri Jun 29, 2012 11:32 am

Re: Getting started with UEFI

Post by blm768 »

Writing that loop made getting the memory map work much better. Thanks!
By the way, what's the best way to get the handle to the EFI File Protocol? It looks like there should be a way to get it from the image handle, but I'm not sure how exactly. Do I just call HandleProtocol() or OpenProtocol() on the image handle?
blm768
Member
Member
Posts: 45
Joined: Fri Jun 29, 2012 11:32 am

Re: Getting started with UEFI

Post by blm768 »

Sorry for the triple post and the bump. Anyway...

Once I get my bootloader working, I'll probably add some of my knowledge to the wiki's UEFI article; it could use a little fleshing out in places. I think the only steps I've got left are getting the handle to the EFI File Protocol and figuring out what I need to to to create the kernel's page tables. I'm hoping to set up my own tables and then somehow free the firmware's identity-mapped ones, but I'm not quite sure how. Once I get those steps working, I should be able to expand the article with some useful stuff.
Post Reply