Page 1 of 1

Own OS UEFI

Posted: Thu Dec 08, 2016 12:49 pm
by adsko
Hi,
actually i'm trying to develop simple os with multitasking on UEFI(EDK2) device and I have few questions.

1) How do protocols works? For example, I need to load kernel by LoadImage but that function needs EFI_DEVICE_PATH_PROTOCOL, how i can get it?

2) LoadImage is a Boot Service. After ExitBootServices I lost that, so is there a simple way to load PE file to memmory or keep Boot Services functions?

Re: Own OS UEFI

Posted: Thu Dec 08, 2016 1:01 pm
by bzt
adsko wrote:Hi,
actually i'm trying to develop simple os with multitasking on UEFI(EDK2) device and I have few questions.

1) How do protocols works? For example, I need to load kernel by LoadImage but that function needs EFI_DEVICE_PATH_PROTOCOL, how i can get it?
The documentation is good enough, and there are plenty of working examples on this. Pick one. In short you have a UUID for a service, you locate it's handler. Using that handler you can reference the service's properties and call it's methods.

Code: Select all

	EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
	EFI_STATUS status = EFI_SUCCESS;
	status = LibLocateProtocol(&GraphicsOutputProtocolUUID, (void **)&gop);
	if (EFI_ERROR(status))
		return NULL;
	// get framebuffer address from GOP property
	ptr=(void*)gop->Mode->FrameBufferBase;
adsko wrote: 2) LoadImage is a Boot Service. After ExitBootServices I lost that, so is there a simple way to load PE file to memmory or keep Boot Services functions?
No. The sole purpose of ExitBootServices is to free resources allocated by Boot Services. But why do you need LoadImage in your kernel? You should have your own disk and filesystem driver.

Re: Own OS UEFI

Posted: Thu Dec 08, 2016 1:09 pm
by adsko
Thanks for response.
bzt wrote:No. The sole purpose of ExitBootServices is to free resources allocated by Boot Services. But why do you need LoadImage in your kernel? You should have your own disk and filesystem driver.
Probably yes, but I dont have so much time to write own filesystem driver so i think about keep LoadImage after ExitBootServices.

Re: Own OS UEFI

Posted: Fri Dec 09, 2016 7:42 am
by bzt
adsko wrote: Probably yes, but I dont have so much time to write own filesystem driver so i think about keep LoadImage after ExitBootServices.
Well, you cannot do that. After ExitBootServices no UEFI memory allocation will be done, which is (obviously) a requirement for LoadImage.

Btw, it does not require much time to write a very simple filesystem driver (3 minutes if I'm tired). I'd suggest to put all of your files in an archive (cpio or tar), load that with LoadImage and later in your kernel look up files in the archive.

Code: Select all

unsigned char *tar_getfile(unsigned char *ptr, char *filename)
{
	int k=strlen((unsigned char*)filename);
	while(!memcmp(ptr+257,"ustar",5)){
		int fs=oct2bin(ptr+0x7c,11);
		if(!memcmp(ptr, kernel, k+1)){
			return (unsigned char*)(ptr+512);
		}
		ptr+=(((fs+511)/512)+1)*512;
	}
	return NULL;
}
This code will receive two pointers as input: first points to the tar archive in memory, the second is a pointer to the full path filename you want to load. It will locate the file and return it's address or NULL if file not found. If you create your disk image in a trivial way, then the archive (along with the files in it) would be continuous, meaning you don't have to worry about fragmentation at all.

Re: Own OS UEFI

Posted: Wed Dec 14, 2016 10:54 am
by adsko
I have another problem.
After ExitBootServices, I want to set my own GDT, so I've crated a simple array with five descriptors and 4gb limit for each. After that I've created 48bit GDTR where I've set a limit and an address, finally I've called asm code which should set GDTR and make a long jump. But after a long jump QEMU throw error.

Code: Select all

qemu: fatal: Trying to execute code outside RAM or ROM at 0x000b0000

EAX=065859a0 EBX=065859a0 ECX=00000092 EDX=00000002
ESI=0705ea90 EDI=00000000 EBP=07fafd3c ESP=07fafce4
EIP=000affde EFL=00000086 [--S--P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0008 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0008 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0008 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0008 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0008 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     065859a8 00000017
IDT=     07c5d010 000007ff
CR0=40000033 CR2=00000000 CR3=00000000 CR4=00000648
DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000 
DR6=ffff0ff0 DR7=00000400
CCS=065859a0 CCD=065859b7 CCO=ADDB    
EFER=0000000000000000
FCW=027f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80
FPR0=0000000000000000 0000 FPR1=0000000000000000 0000
FPR2=0000000000000000 0000 FPR3=0000000000000000 0000
FPR4=0000000000000000 0000 FPR5=0000000000000000 0000
FPR6=0000000000000000 0000 FPR7=0000000000000000 0000
XMM00=00000000000000000000000000000000 XMM01=00000000000000000000000000000000
XMM02=00000000000000000000000000000000 XMM03=00000000000000000000000000000000
XMM04=00000000000000000000000000000000 XMM05=00000000000000000000000000000000
XMM06=00000000000000000000000000000000 XMM07=00000000000000000000000000000000
My asm code:

Code: Select all

	__asm__ (
		"cli \n"
		"lgdt (%0) \n"
		"ljmp $0x08, $complete_flush \n"
		"complete_flush: \n"
		"movw $0x10, %%ax \n"
		"movw %%ax, %%ds \n"
		"movw %%ax, %%es \n"
		"movw %%ax, %%fs \n"
		"movw %%ax, %%gs \n"
		"movw %%ax, %%ss \n"
		"ret\n\t"
	:
	:	"b" (&gp), "i"(0x08)
	);
where gp is:

Code: Select all

struct gdt_ptr
{
    unsigned short limit;
    unsigned int base;
} __attribute__((packed));

Re: Own OS UEFI

Posted: Fri Jan 06, 2017 12:10 pm
by albus95
I would also interested in the get question, i me too try to install get and idt based on uefi but with no success yet.
But in my case I have three loader one that is the main uefi loader that load another uefi program that set up different think and than load and start the kernel that is in a DLL.

Re: Own OS UEFI

Posted: Fri Jan 06, 2017 1:08 pm
by crunch
adsko wrote:I have another problem.
After ExitBootServices, I want to set my own GDT, so I've crated a simple array with five descriptors and 4gb limit for each. After that I've created 48bit GDTR where I've set a limit and an address, finally I've called asm code which should set GDTR and make a long jump. But after a long jump QEMU throw error.

Code: Select all

qemu: fatal: Trying to execute code outside RAM or ROM at 0x000b0000

EAX=065859a0 EBX=065859a0 ECX=00000092 EDX=00000002
ESI=0705ea90 EDI=00000000 EBP=07fafd3c ESP=07fafce4
EIP=000affde EFL=00000086 [--S--P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0008 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00cf9a00 DPL=0 CS32 [-R-]
SS =0008 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
DS =0008 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
FS =0008 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
GS =0008 00000000 ffffffff 00cf9300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     065859a8 00000017
The GDT base address looks bogus to me. However the limit appears to be the correct value. Is your GDT aligned to a 16 byte boundary?
EDIT: just saw you wrote that you have 5 descriptors. Which means the limit is also wrong.
I haven't written any UEFI code so I'm out of my depth here. Try doing lgdt and then just hlt'ing, and check the GDTR value qemu

Re: Own OS UEFI

Posted: Fri Jan 06, 2017 2:20 pm
by dchapiesky
Apache Licensed UEFI loader from Intel...

https://github.com/01org/ikgt-uefi-loader