efi: add experimental efi bootloader
this is basically a port of 9boot to EFI. theres support for IA32 (386) and X64 (amd64). has been tested only under qemu with OVMF so far.
This commit is contained in:
parent
0a6439a1f5
commit
6f3dfb57eb
8 changed files with 1426 additions and 0 deletions
272
sys/src/boot/efi/efi.c
Normal file
272
sys/src/boot/efi/efi.c
Normal file
|
@ -0,0 +1,272 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include "fns.h"
|
||||||
|
#include "efi.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
MAXPATH = 128,
|
||||||
|
};
|
||||||
|
|
||||||
|
UINTN MK;
|
||||||
|
EFI_HANDLE *IH;
|
||||||
|
EFI_SYSTEM_TABLE *ST;
|
||||||
|
|
||||||
|
EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
|
||||||
|
EFI_FILE_PROTOCOL *root;
|
||||||
|
|
||||||
|
void
|
||||||
|
putc(int c)
|
||||||
|
{
|
||||||
|
CHAR16 w[2];
|
||||||
|
|
||||||
|
w[0] = c;
|
||||||
|
w[1] = 0;
|
||||||
|
eficall(2, ST->ConOut->OutputString, ST->ConOut, w);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
getc(void)
|
||||||
|
{
|
||||||
|
EFI_INPUT_KEY k;
|
||||||
|
|
||||||
|
if(eficall(2, ST->ConIn->ReadKeyStroke, ST->ConIn, &k))
|
||||||
|
return 0;
|
||||||
|
return k.UnicodeChar;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
usleep(int us)
|
||||||
|
{
|
||||||
|
eficall(1, ST->BootServices->Stall, (UINTN)us);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
unload(void)
|
||||||
|
{
|
||||||
|
eficall(2, ST->BootServices->ExitBootServices, IH, MK);
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
LocateProtocol(EFI_GUID *guid, void *reg, void **pif)
|
||||||
|
{
|
||||||
|
return eficall(3, ST->BootServices->LocateProtocol, guid, reg, pif);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
fsinit(void)
|
||||||
|
{
|
||||||
|
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *fs;
|
||||||
|
|
||||||
|
fs = nil;
|
||||||
|
root = nil;
|
||||||
|
if(LocateProtocol(&EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID, nil, &fs))
|
||||||
|
return;
|
||||||
|
if(eficall(2, fs->OpenVolume, fs, &root)){
|
||||||
|
root = nil;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
towpath(CHAR16 *w, int nw, char *s)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i=0; *s && i<nw-1; i++){
|
||||||
|
*w = *s++;
|
||||||
|
if(*w == '/')
|
||||||
|
*w = '\\';
|
||||||
|
w++;
|
||||||
|
}
|
||||||
|
*w = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_FILE_PROTOCOL*
|
||||||
|
fswalk(EFI_FILE_PROTOCOL *dir, char *name)
|
||||||
|
{
|
||||||
|
CHAR16 wname[MAXPATH];
|
||||||
|
EFI_FILE_PROTOCOL *fp;
|
||||||
|
|
||||||
|
towpath(wname, MAXPATH, name);
|
||||||
|
|
||||||
|
fp = nil;
|
||||||
|
if(eficall(5, dir->Open, dir, &fp, wname, (UINT64)1, (UINT64)1))
|
||||||
|
return nil;
|
||||||
|
return fp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
read(void *f, void *data, int len)
|
||||||
|
{
|
||||||
|
UINTN size;
|
||||||
|
|
||||||
|
size = len;
|
||||||
|
if(eficall(3, ((EFI_FILE_PROTOCOL*)f)->Read, f, &size, data))
|
||||||
|
return 0;
|
||||||
|
return (int)size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
close(void *f)
|
||||||
|
{
|
||||||
|
eficall(1, ((EFI_FILE_PROTOCOL*)f)->Close, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
memconf(char **cfg)
|
||||||
|
{
|
||||||
|
static uchar memtype[EfiMaxMemoryType] = {
|
||||||
|
[EfiReservedMemoryType] 2,
|
||||||
|
[EfiLoaderCode] 1,
|
||||||
|
[EfiLoaderData] 1,
|
||||||
|
[EfiBootServicesCode] 1,
|
||||||
|
[EfiBootServicesData] 1,
|
||||||
|
[EfiRuntimeServicesCode] 1,
|
||||||
|
[EfiRuntimeServicesData] 1,
|
||||||
|
[EfiConventionalMemory] 1,
|
||||||
|
[EfiUnusableMemory] 2,
|
||||||
|
[EfiACPIReclaimMemory] 3,
|
||||||
|
[EfiACPIMemoryNVS] 4,
|
||||||
|
[EfiMemoryMappedIO] 2,
|
||||||
|
[EfiMemoryMappedIOPortSpace] 2,
|
||||||
|
[EfiPalCode] 2,
|
||||||
|
};
|
||||||
|
UINTN mapsize, entsize;
|
||||||
|
EFI_MEMORY_DESCRIPTOR *t;
|
||||||
|
uchar mapbuf[96*1024], *p, m;
|
||||||
|
UINT32 entvers;
|
||||||
|
char *s;
|
||||||
|
|
||||||
|
mapsize = sizeof(mapbuf);
|
||||||
|
entsize = sizeof(EFI_MEMORY_DESCRIPTOR);
|
||||||
|
entvers = 1;
|
||||||
|
if(eficall(5, ST->BootServices->GetMemoryMap, &mapsize, mapbuf, &MK, &entsize, &entvers))
|
||||||
|
return;
|
||||||
|
|
||||||
|
s = *cfg;
|
||||||
|
for(p = mapbuf; mapsize >= entsize; p += entsize, mapsize -= entsize){
|
||||||
|
t = (EFI_MEMORY_DESCRIPTOR*)p;
|
||||||
|
|
||||||
|
m = 0;
|
||||||
|
if(t->Type < EfiMaxMemoryType)
|
||||||
|
m = memtype[t->Type];
|
||||||
|
|
||||||
|
if(m == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(s == *cfg)
|
||||||
|
memmove(s, "*e820=", 6), s += 6;
|
||||||
|
s = hexfmt(s, 1, m), *s++ = ' ';
|
||||||
|
s = hexfmt(s, 16, t->PhysicalStart), *s++ = ' ';
|
||||||
|
s = hexfmt(s, 16, t->PhysicalStart + t->NumberOfPages * 4096ULL), *s++ = ' ';
|
||||||
|
}
|
||||||
|
*s = '\0';
|
||||||
|
if(s > *cfg){
|
||||||
|
s[-1] = '\n';
|
||||||
|
print(*cfg);
|
||||||
|
*cfg = s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
acpiconf(char **cfg)
|
||||||
|
{
|
||||||
|
EFI_CONFIGURATION_TABLE *t;
|
||||||
|
uintptr pa;
|
||||||
|
char *s;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
pa = 0;
|
||||||
|
t = ST->ConfigurationTable;
|
||||||
|
n = ST->NumberOfTableEntries;
|
||||||
|
while(--n >= 0){
|
||||||
|
if(memcmp(&t->VendorGuid, &ACPI_10_TABLE_GUID, sizeof(EFI_GUID)) == 0){
|
||||||
|
if(pa == 0)
|
||||||
|
pa = (uintptr)t->VendorTable;
|
||||||
|
} else if(memcmp(&t->VendorGuid, &ACPI_20_TABLE_GUID, sizeof(EFI_GUID)) == 0)
|
||||||
|
pa = (uintptr)t->VendorTable;
|
||||||
|
t++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pa){
|
||||||
|
s = *cfg;
|
||||||
|
memmove(s, "*acpi=0x", 8), s += 8;
|
||||||
|
s = hexfmt(s, 0, pa), *s++ = '\n';
|
||||||
|
*s = '\0';
|
||||||
|
print(*cfg);
|
||||||
|
*cfg = s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
screenconf(char **cfg)
|
||||||
|
{
|
||||||
|
char *s;
|
||||||
|
|
||||||
|
gop = nil;
|
||||||
|
if(LocateProtocol(&EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID, nil, &gop) || gop == nil)
|
||||||
|
return;
|
||||||
|
|
||||||
|
s = *cfg;
|
||||||
|
memmove(s, "*bootscreen=", 12), s += 12;
|
||||||
|
|
||||||
|
s = decfmt(s, 0, gop->Mode->Info->PixelsPerScanLine), *s++ = 'x';
|
||||||
|
s = decfmt(s, 0, gop->Mode->Info->VerticalResolution), *s++ = 'x';
|
||||||
|
s = decfmt(s, 0, 32), *s++ = ' ';
|
||||||
|
|
||||||
|
memmove(s, "x8r8g8b8", 8), s += 8;
|
||||||
|
*s++ = ' ';
|
||||||
|
|
||||||
|
*s++ = '0', *s++ = 'x';
|
||||||
|
s = hexfmt(s, 0, gop->Mode->FrameBufferBase), *s++ = '\n';
|
||||||
|
*s = '\0';
|
||||||
|
|
||||||
|
print(*cfg);
|
||||||
|
*cfg = s;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Print(" Width="), Printi(gop->Mode->Info->HorizontalResolution), Print("\r\n");
|
||||||
|
Print(" Height="), Printi(gop->Mode->Info->VerticalResolution), Print("\r\n");
|
||||||
|
Print(" Stride="), Printi(gop->Mode->Info->PixelsPerScanLine), Print("\r\n");
|
||||||
|
Print(" PixelFormat="), Printi(gop->Mode->Info->PixelFormat), Print("\r\n");
|
||||||
|
Print(" RedMask="), Printi(gop->Mode->Info->PixelInformation.RedMask), Print("\r\n");
|
||||||
|
Print(" GreenMask="), Printi(gop->Mode->Info->PixelInformation.GreenMask), Print("\r\n");
|
||||||
|
Print(" BlueMask="), Printi(gop->Mode->Info->PixelInformation.BlueMask), Print("\r\n");
|
||||||
|
Print(" FrameBufferBase="), Printi(gop->Mode->FrameBufferBase), Print("\r\n");
|
||||||
|
Print(" FrameBufferSize="), Printi(gop->Mode->FrameBufferSize), Print("\r\n");
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
eficonfig(char **cfg)
|
||||||
|
{
|
||||||
|
screenconf(cfg);
|
||||||
|
acpiconf(cfg);
|
||||||
|
memconf(cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
main(EFI_HANDLE ih, EFI_SYSTEM_TABLE *st)
|
||||||
|
{
|
||||||
|
char path[MAXPATH], *kern;
|
||||||
|
void *f;
|
||||||
|
|
||||||
|
IH = ih;
|
||||||
|
ST = st;
|
||||||
|
|
||||||
|
fsinit();
|
||||||
|
|
||||||
|
f = fswalk(root, "/plan9.ini");
|
||||||
|
for(;;){
|
||||||
|
kern = configure(f, path);
|
||||||
|
f = fswalk(root, kern);
|
||||||
|
if(f == nil){
|
||||||
|
print("not found\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
print(bootkern(f));
|
||||||
|
print("\n");
|
||||||
|
f = nil;
|
||||||
|
}
|
||||||
|
}
|
270
sys/src/boot/efi/efi.h
Normal file
270
sys/src/boot/efi/efi.h
Normal file
|
@ -0,0 +1,270 @@
|
||||||
|
typedef ushort CHAR16;
|
||||||
|
|
||||||
|
typedef uchar UINT8;
|
||||||
|
typedef ushort UINT16;
|
||||||
|
typedef ulong UINT32;
|
||||||
|
typedef uvlong UINT64;
|
||||||
|
|
||||||
|
typedef uintptr UINTN;
|
||||||
|
|
||||||
|
typedef void* EFI_HANDLE;
|
||||||
|
typedef UINT32 EFI_STATUS;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT32 Data1;
|
||||||
|
UINT16 Data2;
|
||||||
|
UINT16 Data3;
|
||||||
|
UINT8 Data4[8];
|
||||||
|
} EFI_GUID;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT16 ScanCode;
|
||||||
|
CHAR16 UnicodeChar;
|
||||||
|
} EFI_INPUT_KEY;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void *Reset;
|
||||||
|
void *ReadKeyStroke;
|
||||||
|
void *WaitForKey;
|
||||||
|
} EFI_SIMPLE_TEXT_INPUT_PROTOCOL;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void *Reset;
|
||||||
|
void *OutputString;
|
||||||
|
void *TestString;
|
||||||
|
void *QueryMode;
|
||||||
|
void *SetMode;
|
||||||
|
void *SetAttribute;
|
||||||
|
void *ClearScreen;
|
||||||
|
void *SetCursorPosition;
|
||||||
|
void *EnableCursor;
|
||||||
|
void *Mode;
|
||||||
|
} EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT32 RedMask;
|
||||||
|
UINT32 GreenMask;
|
||||||
|
UINT32 BlueMask;
|
||||||
|
UINT32 ReservedMask;
|
||||||
|
} EFI_PIXEL_BITMASK;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT32 Version;
|
||||||
|
UINT32 HorizontalResolution;
|
||||||
|
UINT32 VerticalResolution;
|
||||||
|
UINT32 PixelFormat;
|
||||||
|
EFI_PIXEL_BITMASK PixelInformation;
|
||||||
|
UINT32 PixelsPerScanLine;
|
||||||
|
} EFI_GRAPHICS_OUTPUT_MODE_INFORMATION;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT32 MaxMode;
|
||||||
|
UINT32 Mode;
|
||||||
|
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
|
||||||
|
UINTN SizeOfInfo;
|
||||||
|
UINT64 FrameBufferBase;
|
||||||
|
UINTN FrameBufferSize;
|
||||||
|
} EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void *QueryMode;
|
||||||
|
void *SetMode;
|
||||||
|
void *Blt;
|
||||||
|
EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode;
|
||||||
|
} EFI_GRAPHICS_OUTPUT_PROTOCOL;
|
||||||
|
|
||||||
|
EFI_GUID EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID = {
|
||||||
|
0x9042a9de, 0x23dc, 0x4a38,
|
||||||
|
0x96, 0xfb, 0x7a, 0xde,
|
||||||
|
0xd0, 0x80, 0x51, 0x6a,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT64 Revision;
|
||||||
|
void *Open;
|
||||||
|
void *Close;
|
||||||
|
void *Delete;
|
||||||
|
void *Read;
|
||||||
|
void *Write;
|
||||||
|
void *GetPosition;
|
||||||
|
void *SetPosition;
|
||||||
|
void *GetInfo;
|
||||||
|
void *SetInfo;
|
||||||
|
void *Flush;
|
||||||
|
void *OpenEx;
|
||||||
|
void *ReadEx;
|
||||||
|
void *WriteEx;
|
||||||
|
void *FlushEx;
|
||||||
|
} EFI_FILE_PROTOCOL;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT64 Revision;
|
||||||
|
void *OpenVolume;
|
||||||
|
} EFI_SIMPLE_FILE_SYSTEM_PROTOCOL;
|
||||||
|
|
||||||
|
EFI_GUID EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID = {
|
||||||
|
0x0964e5b22, 0x6459, 0x11d2,
|
||||||
|
0x8e, 0x39, 0x00, 0xa0,
|
||||||
|
0xc9, 0x69, 0x72, 0x3b,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
EfiReservedMemoryType,
|
||||||
|
EfiLoaderCode,
|
||||||
|
EfiLoaderData,
|
||||||
|
EfiBootServicesCode,
|
||||||
|
EfiBootServicesData,
|
||||||
|
EfiRuntimeServicesCode,
|
||||||
|
EfiRuntimeServicesData,
|
||||||
|
EfiConventionalMemory,
|
||||||
|
EfiUnusableMemory,
|
||||||
|
EfiACPIReclaimMemory,
|
||||||
|
EfiACPIMemoryNVS,
|
||||||
|
EfiMemoryMappedIO,
|
||||||
|
EfiMemoryMappedIOPortSpace,
|
||||||
|
EfiPalCode,
|
||||||
|
EfiMaxMemoryType,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT32 Type;
|
||||||
|
UINT32 Reserved;
|
||||||
|
UINT64 PhysicalStart;
|
||||||
|
UINT64 VirtualStart;
|
||||||
|
UINT64 NumberOfPages;
|
||||||
|
UINT64 Attribute;
|
||||||
|
} EFI_MEMORY_DESCRIPTOR;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT64 Signature;
|
||||||
|
UINT32 Revision;
|
||||||
|
UINT32 HeaderSize;
|
||||||
|
UINT32 CRC32;
|
||||||
|
UINT32 Reserved;
|
||||||
|
} EFI_TABLE_HEADER;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
EFI_TABLE_HEADER;
|
||||||
|
|
||||||
|
void *RaiseTPL;
|
||||||
|
void *RestoreTPL;
|
||||||
|
void *AllocatePages;
|
||||||
|
void *FreePages;
|
||||||
|
void *GetMemoryMap;
|
||||||
|
void *AllocatePool;
|
||||||
|
void *FreePool;
|
||||||
|
|
||||||
|
void *CreateEvent;
|
||||||
|
void *SetTimer;
|
||||||
|
void *WaitForEvent;
|
||||||
|
void *SignalEvent;
|
||||||
|
void *CloseEvent;
|
||||||
|
void *CheckEvent;
|
||||||
|
|
||||||
|
void **InstallProtocolInterface;
|
||||||
|
void **ReinstallProtocolInterface;
|
||||||
|
void **UninstallProtocolInterface;
|
||||||
|
|
||||||
|
void *HandleProtocol;
|
||||||
|
void *Reserved;
|
||||||
|
void *RegisterProtocolNotify;
|
||||||
|
|
||||||
|
void *LocateHandle;
|
||||||
|
void *LocateDevicePath;
|
||||||
|
void *InstallConfigurationTable;
|
||||||
|
|
||||||
|
void *LoadImage;
|
||||||
|
void *StartImage;
|
||||||
|
void *Exit;
|
||||||
|
void *UnloadImage;
|
||||||
|
void *ExitBootServices;
|
||||||
|
|
||||||
|
void *GetNextMonotonicCount;
|
||||||
|
void *Stall;
|
||||||
|
void *SetWatchdogTimer;
|
||||||
|
|
||||||
|
void *ConnectController;
|
||||||
|
void *DisconnectController;
|
||||||
|
|
||||||
|
void *OpenProtocol;
|
||||||
|
void *CloseProtocol;
|
||||||
|
|
||||||
|
void *OpenProtocolInformation;
|
||||||
|
void *ProtocolsPerHandle;
|
||||||
|
void *LocateHandleBuffer;
|
||||||
|
void *LocateProtocol;
|
||||||
|
|
||||||
|
void *InstallMultipleProtocolInterfaces;
|
||||||
|
void *UninstallMultipleProtocolInterfaces;
|
||||||
|
|
||||||
|
void *CalculateCrc32;
|
||||||
|
|
||||||
|
void *CopyMem;
|
||||||
|
void *SetMem;
|
||||||
|
void *CreateEventEx;
|
||||||
|
} EFI_BOOT_SERVICES;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
EFI_TABLE_HEADER;
|
||||||
|
|
||||||
|
void *GetTime;
|
||||||
|
void *SetTime;
|
||||||
|
void *GetWakeupTime;
|
||||||
|
void *SetWakeupTime;
|
||||||
|
|
||||||
|
void *SetVirtualAddressMap;
|
||||||
|
void *ConvertPointer;
|
||||||
|
|
||||||
|
void *GetVariable;
|
||||||
|
void *GetNextVariableName;
|
||||||
|
void *SetVariable;
|
||||||
|
|
||||||
|
void *GetNextHighMonotonicCount;
|
||||||
|
void *ResetSystem;
|
||||||
|
|
||||||
|
void *UpdateCapsule;
|
||||||
|
void *QueryCapsuleCapabilities;
|
||||||
|
|
||||||
|
void *QueryVariableInfo;
|
||||||
|
} EFI_RUNTIME_SERVICES;
|
||||||
|
|
||||||
|
|
||||||
|
EFI_GUID ACPI_20_TABLE_GUID = {
|
||||||
|
0x8868e871, 0xe4f1, 0x11d3,
|
||||||
|
0xbc, 0x22, 0x00, 0x80,
|
||||||
|
0xc7, 0x3c, 0x88, 0x81,
|
||||||
|
};
|
||||||
|
|
||||||
|
EFI_GUID ACPI_10_TABLE_GUID = {
|
||||||
|
0xeb9d2d30, 0x2d88, 0x11d3,
|
||||||
|
0x9a, 0x16, 0x00, 0x90,
|
||||||
|
0x27, 0x3f, 0xc1, 0x4d,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
EFI_GUID VendorGuid;
|
||||||
|
void *VendorTable;
|
||||||
|
} EFI_CONFIGURATION_TABLE;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
EFI_TABLE_HEADER;
|
||||||
|
|
||||||
|
CHAR16 *FirmwareVendor;
|
||||||
|
UINT32 FirmwareRevision;
|
||||||
|
|
||||||
|
EFI_HANDLE ConsoleInHandle;
|
||||||
|
EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn;
|
||||||
|
|
||||||
|
EFI_HANDLE ConsoleOutHandle;
|
||||||
|
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut;
|
||||||
|
|
||||||
|
EFI_HANDLE StandardErrorHandle;
|
||||||
|
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *StdErr;
|
||||||
|
|
||||||
|
EFI_RUNTIME_SERVICES *RuntimeServices;
|
||||||
|
EFI_BOOT_SERVICES *BootServices;
|
||||||
|
|
||||||
|
UINTN NumberOfTableEntries;
|
||||||
|
EFI_CONFIGURATION_TABLE *ConfigurationTable;
|
||||||
|
} EFI_SYSTEM_TABLE;
|
29
sys/src/boot/efi/fns.h
Normal file
29
sys/src/boot/efi/fns.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
extern char hex[];
|
||||||
|
|
||||||
|
void usleep(int t);
|
||||||
|
void jump(void *pc);
|
||||||
|
|
||||||
|
int read(void *f, void *data, int len);
|
||||||
|
int readn(void *f, void *data, int len);
|
||||||
|
void close(void *f);
|
||||||
|
void unload(void);
|
||||||
|
|
||||||
|
int getc(void);
|
||||||
|
void putc(int c);
|
||||||
|
|
||||||
|
void memset(void *p, int v, int n);
|
||||||
|
void memmove(void *dst, void *src, int n);
|
||||||
|
int memcmp(void *src, void *dst, int n);
|
||||||
|
int strlen(char *s);
|
||||||
|
char *strchr(char *s, int c);
|
||||||
|
char *strrchr(char *s, int c);
|
||||||
|
void print(char *s);
|
||||||
|
|
||||||
|
char *configure(void *f, char *path);
|
||||||
|
char *bootkern(void *f);
|
||||||
|
|
||||||
|
char *hexfmt(char *s, int i, uvlong a);
|
||||||
|
char *decfmt(char *s, int i, ulong a);
|
||||||
|
|
||||||
|
long eficall(long narg, void *proc, ...);
|
||||||
|
void eficonfig(char **cfg);
|
47
sys/src/boot/efi/mem.h
Normal file
47
sys/src/boot/efi/mem.h
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* Memory and machine-specific definitions. Used in C and assembler.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sizes
|
||||||
|
*/
|
||||||
|
#define BI2BY 8 /* bits per byte */
|
||||||
|
#define BI2WD 32 /* bits per word */
|
||||||
|
#define BY2WD 4 /* bytes per word */
|
||||||
|
#define BY2PG 4096 /* bytes per page */
|
||||||
|
#define WD2PG (BY2PG/BY2WD) /* words per page */
|
||||||
|
#define PGSHIFT 12 /* log(BY2PG) */
|
||||||
|
#define PGROUND(s) (((s)+(BY2PG-1))&~(BY2PG-1))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fundamental addresses
|
||||||
|
*/
|
||||||
|
#define CONFADDR 0x1200 /* info passed from boot loader */
|
||||||
|
#define BIOSXCHG 0x6000 /* To exchange data with the BIOS */
|
||||||
|
|
||||||
|
#define SELGDT (0<<3) /* selector is in gdt */
|
||||||
|
#define SELLDT (1<<3) /* selector is in ldt */
|
||||||
|
|
||||||
|
#define SELECTOR(i, t, p) (((i)<<3) | (t) | (p))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fields in segment descriptors
|
||||||
|
*/
|
||||||
|
#define SEGDATA (0x10<<8) /* data/stack segment */
|
||||||
|
#define SEGEXEC (0x18<<8) /* executable segment */
|
||||||
|
#define SEGTSS (0x9<<8) /* TSS segment */
|
||||||
|
#define SEGCG (0x0C<<8) /* call gate */
|
||||||
|
#define SEGIG (0x0E<<8) /* interrupt gate */
|
||||||
|
#define SEGTG (0x0F<<8) /* trap gate */
|
||||||
|
#define SEGLDT (0x02<<8) /* local descriptor table */
|
||||||
|
#define SEGTYPE (0x1F<<8)
|
||||||
|
|
||||||
|
#define SEGP (1<<15) /* segment present */
|
||||||
|
#define SEGPL(x) ((x)<<13) /* priority level */
|
||||||
|
#define SEGB (1<<22) /* granularity 1==4k (for expand-down) */
|
||||||
|
#define SEGD (1<<22) /* default 1==32bit (for code) */
|
||||||
|
#define SEGE (1<<10) /* expand down */
|
||||||
|
#define SEGW (1<<9) /* writable (for data/stack) */
|
||||||
|
#define SEGR (1<<9) /* readable (for code) */
|
||||||
|
#define SEGL (1<<21) /* 64 bit */
|
||||||
|
#define SEGG (1<<23) /* granularity 1==4k (for other) */
|
43
sys/src/boot/efi/mkfile
Normal file
43
sys/src/boot/efi/mkfile
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
TARG=bootia32.efi bootx64.efi
|
||||||
|
HFILES=fns.h mem.h
|
||||||
|
IMAGEBASE=0x8000
|
||||||
|
PEFLAGS=$CFLAGS '-DIMAGEBASE='$IMAGEBASE
|
||||||
|
|
||||||
|
all:V: $TARG
|
||||||
|
|
||||||
|
install:V: $TARG
|
||||||
|
cp bootia32.efi /386
|
||||||
|
cp bootx64.efi /386
|
||||||
|
|
||||||
|
bootia32.efi: pe32.8 efi.8 sub.8
|
||||||
|
8l -l -H3 -T$IMAGEBASE -o $target $prereq
|
||||||
|
|
||||||
|
pe32.8: pe32.s
|
||||||
|
8a $PEFLAGS pe32.s
|
||||||
|
|
||||||
|
efi.8: efi.c efi.h
|
||||||
|
8c $CFLAGS efi.c
|
||||||
|
|
||||||
|
sub.8: sub.c
|
||||||
|
8c $CFLAGS sub.c
|
||||||
|
|
||||||
|
%.8: $HFILES
|
||||||
|
|
||||||
|
|
||||||
|
bootx64.efi: pe64.6 efi.6 sub.6
|
||||||
|
6l -l -s -R1 -T$IMAGEBASE -o bootx64.out $prereq
|
||||||
|
dd -if bootx64.out -bs 1 -iseek 40 >$target
|
||||||
|
|
||||||
|
pe64.6: pe64.s
|
||||||
|
6a $PEFLAGS pe64.s
|
||||||
|
|
||||||
|
efi.6: efi.c efi.h
|
||||||
|
6c $CFLAGS efi.c
|
||||||
|
|
||||||
|
sub.6: sub.c
|
||||||
|
6c $CFLAGS sub.c
|
||||||
|
|
||||||
|
%.6: $HFILES
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.[68] *.out $TARG
|
149
sys/src/boot/efi/pe32.s
Normal file
149
sys/src/boot/efi/pe32.s
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
TEXT mzhdr(SB), 1, $0
|
||||||
|
BYTE $'M'; BYTE $'Z'
|
||||||
|
|
||||||
|
WORD $0 /* e_cblp UNUSED */
|
||||||
|
WORD $0 /* e_cp UNUSED */
|
||||||
|
WORD $0 /* e_crlc UNUSED */
|
||||||
|
WORD $0 /* e_cparhdr UNUSED */
|
||||||
|
WORD $0 /* e_minalloc UNUSED */
|
||||||
|
WORD $0 /* e_maxalloc UNUSED */
|
||||||
|
WORD $0 /* e_ss UNUSED */
|
||||||
|
WORD $0 /* e_sp UNUSED */
|
||||||
|
WORD $0 /* e_csum UNUSED */
|
||||||
|
WORD $0 /* e_ip UNUSED */
|
||||||
|
WORD $0 /* e_cs UNUSED */
|
||||||
|
WORD $0 /* e_lsarlc UNUSED */
|
||||||
|
WORD $0 /* e_ovno UNUSED */
|
||||||
|
|
||||||
|
WORD $0 /* e_res UNUSED */
|
||||||
|
WORD $0
|
||||||
|
WORD $0
|
||||||
|
WORD $0
|
||||||
|
WORD $0
|
||||||
|
|
||||||
|
WORD $0 /* e_oemid UNUSED */
|
||||||
|
|
||||||
|
WORD $0 /* e_res2 UNUSED */
|
||||||
|
WORD $0
|
||||||
|
WORD $0
|
||||||
|
WORD $0
|
||||||
|
WORD $0
|
||||||
|
WORD $0
|
||||||
|
WORD $0
|
||||||
|
WORD $0
|
||||||
|
WORD $0
|
||||||
|
WORD $0
|
||||||
|
|
||||||
|
LONG $pehdr-IMAGEBASE(SB) /* offset to pe header */
|
||||||
|
|
||||||
|
TEXT pehdr(SB), 1, $0
|
||||||
|
BYTE $'P'; BYTE $'E'; BYTE $0; BYTE $0
|
||||||
|
|
||||||
|
WORD $0x014C /* Machine (Intel 386) */
|
||||||
|
WORD $1 /* NumberOfSections */
|
||||||
|
LONG $0 /* TimeDateStamp UNUSED */
|
||||||
|
LONG $0 /* PointerToSymbolTable UNUSED */
|
||||||
|
LONG $0 /* NumberOfSymbols UNUSED */
|
||||||
|
WORD $0xE0 /* SizeOfOptionalHeader */
|
||||||
|
WORD $2103 /* Characteristics (no relocations, executable, 32 bit) */
|
||||||
|
|
||||||
|
WORD $0x10B /* Magic (PE32) */
|
||||||
|
BYTE $9 /* MajorLinkerVersion UNUSED */
|
||||||
|
BYTE $0 /* MinorLinkerVersion UNUSED */
|
||||||
|
LONG $0 /* SizeOfCode UNUSED */
|
||||||
|
LONG $0 /* SizeOfInitializedData UNUSED */
|
||||||
|
LONG $0 /* SizeOfUninitializedData UNUSED */
|
||||||
|
LONG $start-IMAGEBASE(SB)/* AddressOfEntryPoint */
|
||||||
|
LONG $0 /* BaseOfCode UNUSED */
|
||||||
|
LONG $0 /* BaseOfData UNUSED */
|
||||||
|
LONG $IMAGEBASE /* ImageBase */
|
||||||
|
LONG $0x200 /* SectionAlignment */
|
||||||
|
LONG $0x200 /* FileAlignment */
|
||||||
|
WORD $4 /* MajorOperatingSystemVersion UNUSED */
|
||||||
|
WORD $0 /* MinorOperatingSystemVersion UNUSED */
|
||||||
|
WORD $0 /* MajorImageVersion UNUSED */
|
||||||
|
WORD $0 /* MinorImageVersion UNUSED */
|
||||||
|
WORD $4 /* MajorSubsystemVersion */
|
||||||
|
WORD $0 /* MinorSubsystemVersion UNUSED */
|
||||||
|
LONG $0 /* Win32VersionValue UNUSED */
|
||||||
|
LONG $end-IMAGEBASE(SB) /* SizeOfImage */
|
||||||
|
LONG $start-IMAGEBASE(SB)/* SizeOfHeaders */
|
||||||
|
LONG $0 /* CheckSum UNUSED */
|
||||||
|
WORD $10 /* Subsystem (10 = efi application) */
|
||||||
|
WORD $0 /* DllCharacteristics UNUSED */
|
||||||
|
LONG $0 /* SizeOfStackReserve UNUSED */
|
||||||
|
LONG $0 /* SizeOfStackCommit UNUSED */
|
||||||
|
LONG $0 /* SizeOfHeapReserve UNUSED */
|
||||||
|
LONG $0 /* SizeOfHeapCommit UNUSED */
|
||||||
|
LONG $0 /* LoaderFlags UNUSED */
|
||||||
|
LONG $16 /* NumberOfRvaAndSizes UNUSED */
|
||||||
|
|
||||||
|
LONG $0; LONG $0
|
||||||
|
LONG $0; LONG $0
|
||||||
|
LONG $0; LONG $0 /* RVA */
|
||||||
|
LONG $0; LONG $0 /* RVA */
|
||||||
|
LONG $0; LONG $0 /* RVA */
|
||||||
|
LONG $0; LONG $0 /* RVA */
|
||||||
|
LONG $0; LONG $0 /* RVA */
|
||||||
|
LONG $0; LONG $0 /* RVA */
|
||||||
|
LONG $0; LONG $0 /* RVA */
|
||||||
|
LONG $0; LONG $0 /* RVA */
|
||||||
|
LONG $0; LONG $0 /* RVA */
|
||||||
|
LONG $0; LONG $0 /* RVA */
|
||||||
|
LONG $0; LONG $0 /* RVA */
|
||||||
|
LONG $0; LONG $0 /* RVA */
|
||||||
|
LONG $0; LONG $0 /* RVA */
|
||||||
|
LONG $0; LONG $0 /* RVA */
|
||||||
|
|
||||||
|
BYTE $'.'; BYTE $'t'; BYTE $'e'; BYTE $'x'
|
||||||
|
BYTE $'t'; BYTE $0; BYTE $0; BYTE $0
|
||||||
|
LONG $edata-(IMAGEBASE+0x200)(SB) /* VirtualSize */
|
||||||
|
LONG $start-IMAGEBASE(SB) /* VirtualAddress */
|
||||||
|
LONG $edata-(IMAGEBASE+0x200)(SB) /* SizeOfData */
|
||||||
|
LONG $start-IMAGEBASE(SB) /* PointerToRawData */
|
||||||
|
LONG $0 /* PointerToRelocations UNUSED */
|
||||||
|
LONG $0 /* PointerToLinenumbers UNUSED */
|
||||||
|
WORD $0 /* NumberOfRelocations UNUSED */
|
||||||
|
WORD $0 /* NumberOfLinenumbers UNUSED */
|
||||||
|
LONG $0x86000020 /* Characteristics (code, execute, read, write) */
|
||||||
|
|
||||||
|
/* padding to get start(SB) at IMAGEBASE+0x200 */
|
||||||
|
LONG $0; LONG $0; LONG $0; LONG $0;
|
||||||
|
LONG $0; LONG $0; LONG $0; LONG $0;
|
||||||
|
LONG $0; LONG $0; LONG $0; LONG $0;
|
||||||
|
LONG $0; LONG $0; LONG $0; LONG $0;
|
||||||
|
LONG $0; LONG $0; LONG $0; LONG $0;
|
||||||
|
LONG $0; LONG $0; LONG $0; LONG $0;
|
||||||
|
LONG $0; LONG $0; LONG $0; LONG $0;
|
||||||
|
LONG $0; LONG $0; LONG $0; LONG $0;
|
||||||
|
LONG $0; LONG $0; LONG $0; LONG $0;
|
||||||
|
LONG $0; LONG $0; LONG $0; LONG $0;
|
||||||
|
|
||||||
|
TEXT start(SB), 1, $0
|
||||||
|
CALL reloc(SP)
|
||||||
|
|
||||||
|
TEXT reloc(SB), 1, $0
|
||||||
|
MOVL 0(SP), SI
|
||||||
|
SUBL $reloc-IMAGEBASE(SB), SI
|
||||||
|
MOVL $IMAGEBASE, DI
|
||||||
|
MOVL $edata-IMAGEBASE(SB), CX
|
||||||
|
CLD
|
||||||
|
REP; MOVSB
|
||||||
|
MOVL $main(SB), DI
|
||||||
|
MOVL DI, (SP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT jump(SB), $0
|
||||||
|
CLI
|
||||||
|
MOVL 4(SP), AX
|
||||||
|
JMP *AX
|
||||||
|
|
||||||
|
|
||||||
|
TEXT eficall(SB), 1, $0
|
||||||
|
MOVL 0(SP), DI /* saved by callee */
|
||||||
|
MOVL 8(SP), AX
|
||||||
|
ADDL $12, SP
|
||||||
|
CALL AX
|
||||||
|
SUBL $12, SP
|
||||||
|
MOVL DI, 0(SP)
|
||||||
|
RET
|
234
sys/src/boot/efi/pe64.s
Normal file
234
sys/src/boot/efi/pe64.s
Normal file
|
@ -0,0 +1,234 @@
|
||||||
|
TEXT mzhdr(SB), 1, $0
|
||||||
|
BYTE $'M'; BYTE $'Z'
|
||||||
|
|
||||||
|
WORD $0 /* e_cblp UNUSED */
|
||||||
|
WORD $0 /* e_cp UNUSED */
|
||||||
|
WORD $0 /* e_crlc UNUSED */
|
||||||
|
WORD $0 /* e_cparhdr UNUSED */
|
||||||
|
WORD $0 /* e_minalloc UNUSED */
|
||||||
|
WORD $0 /* e_maxalloc UNUSED */
|
||||||
|
WORD $0 /* e_ss UNUSED */
|
||||||
|
WORD $0 /* e_sp UNUSED */
|
||||||
|
WORD $0 /* e_csum UNUSED */
|
||||||
|
WORD $0 /* e_ip UNUSED */
|
||||||
|
WORD $0 /* e_cs UNUSED */
|
||||||
|
WORD $0 /* e_lsarlc UNUSED */
|
||||||
|
WORD $0 /* e_ovno UNUSED */
|
||||||
|
|
||||||
|
WORD $0 /* e_res UNUSED */
|
||||||
|
WORD $0
|
||||||
|
WORD $0
|
||||||
|
WORD $0
|
||||||
|
WORD $0
|
||||||
|
|
||||||
|
WORD $0 /* e_oemid UNUSED */
|
||||||
|
|
||||||
|
WORD $0 /* e_res2 UNUSED */
|
||||||
|
WORD $0
|
||||||
|
WORD $0
|
||||||
|
WORD $0
|
||||||
|
WORD $0
|
||||||
|
WORD $0
|
||||||
|
WORD $0
|
||||||
|
WORD $0
|
||||||
|
WORD $0
|
||||||
|
WORD $0
|
||||||
|
|
||||||
|
LONG $pehdr-IMAGEBASE(SB) /* offset to pe header */
|
||||||
|
|
||||||
|
TEXT pehdr(SB), 1, $0
|
||||||
|
BYTE $'P'; BYTE $'E'; BYTE $0; BYTE $0
|
||||||
|
|
||||||
|
WORD $0x8664 /* Machine (AMD64) */
|
||||||
|
WORD $1 /* NumberOfSections */
|
||||||
|
LONG $0 /* TimeDateStamp UNUSED */
|
||||||
|
LONG $0 /* PointerToSymbolTable UNUSED */
|
||||||
|
LONG $0 /* NumberOfSymbols UNUSED */
|
||||||
|
WORD $0xF0 /* SizeOfOptionalHeader */
|
||||||
|
WORD $2223 /* Characteristics */
|
||||||
|
|
||||||
|
WORD $0x20B /* Magic (PE32+) */
|
||||||
|
BYTE $9 /* MajorLinkerVersion UNUSED */
|
||||||
|
BYTE $0 /* MinorLinkerVersion UNUSED */
|
||||||
|
LONG $0 /* SizeOfCode UNUSED */
|
||||||
|
LONG $0 /* SizeOfInitializedData UNUSED */
|
||||||
|
LONG $0 /* SizeOfUninitializedData UNUSED */
|
||||||
|
LONG $start-IMAGEBASE(SB)/* AddressOfEntryPoint */
|
||||||
|
LONG $0 /* BaseOfCode UNUSED */
|
||||||
|
|
||||||
|
QUAD $IMAGEBASE /* ImageBase */
|
||||||
|
LONG $0x200 /* SectionAlignment */
|
||||||
|
LONG $0x200 /* FileAlignment */
|
||||||
|
WORD $4 /* MajorOperatingSystemVersion UNUSED */
|
||||||
|
WORD $0 /* MinorOperatingSystemVersion UNUSED */
|
||||||
|
WORD $0 /* MajorImageVersion UNUSED */
|
||||||
|
WORD $0 /* MinorImageVersion UNUSED */
|
||||||
|
WORD $4 /* MajorSubsystemVersion */
|
||||||
|
WORD $0 /* MinorSubsystemVersion UNUSED */
|
||||||
|
LONG $0 /* Win32VersionValue UNUSED */
|
||||||
|
LONG $end-IMAGEBASE(SB) /* SizeOfImage */
|
||||||
|
LONG $start-IMAGEBASE(SB)/* SizeOfHeaders */
|
||||||
|
LONG $0 /* CheckSum UNUSED */
|
||||||
|
WORD $10 /* Subsystem (10 = efi application) */
|
||||||
|
WORD $0 /* DllCharacteristics UNUSED */
|
||||||
|
QUAD $0 /* SizeOfStackReserve UNUSED */
|
||||||
|
QUAD $0 /* SizeOfStackCommit UNUSED */
|
||||||
|
QUAD $0 /* SizeOfHeapReserve UNUSED */
|
||||||
|
QUAD $0 /* SizeOfHeapCommit UNUSED */
|
||||||
|
LONG $0 /* LoaderFlags UNUSED */
|
||||||
|
LONG $16 /* NumberOfRvaAndSizes UNUSED */
|
||||||
|
|
||||||
|
LONG $0; LONG $0
|
||||||
|
LONG $0; LONG $0
|
||||||
|
LONG $0; LONG $0 /* RVA */
|
||||||
|
LONG $0; LONG $0 /* RVA */
|
||||||
|
LONG $0; LONG $0 /* RVA */
|
||||||
|
LONG $0; LONG $0 /* RVA */
|
||||||
|
LONG $0; LONG $0 /* RVA */
|
||||||
|
LONG $0; LONG $0 /* RVA */
|
||||||
|
LONG $0; LONG $0 /* RVA */
|
||||||
|
LONG $0; LONG $0 /* RVA */
|
||||||
|
LONG $0; LONG $0 /* RVA */
|
||||||
|
LONG $0; LONG $0 /* RVA */
|
||||||
|
LONG $0; LONG $0 /* RVA */
|
||||||
|
LONG $0; LONG $0 /* RVA */
|
||||||
|
LONG $0; LONG $0 /* RVA */
|
||||||
|
LONG $0; LONG $0 /* RVA */
|
||||||
|
|
||||||
|
BYTE $'.'; BYTE $'t'; BYTE $'e'; BYTE $'x'
|
||||||
|
BYTE $'t'; BYTE $0; BYTE $0; BYTE $0
|
||||||
|
LONG $edata-(IMAGEBASE+0x200)(SB) /* VirtualSize */
|
||||||
|
LONG $start-IMAGEBASE(SB) /* VirtualAddress */
|
||||||
|
LONG $edata-(IMAGEBASE+0x200)(SB) /* SizeOfData */
|
||||||
|
LONG $start-IMAGEBASE(SB) /* PointerToRawData */
|
||||||
|
LONG $0 /* PointerToRelocations UNUSED */
|
||||||
|
LONG $0 /* PointerToLinenumbers UNUSED */
|
||||||
|
WORD $0 /* NumberOfRelocations UNUSED */
|
||||||
|
WORD $0 /* NumberOfLinenumbers UNUSED */
|
||||||
|
LONG $0x86000020 /* Characteristics (code, execute, read, write) */
|
||||||
|
|
||||||
|
/* padding to get start(SB) at IMAGEBASE+0x200 */
|
||||||
|
LONG $0; LONG $0; LONG $0; LONG $0;
|
||||||
|
LONG $0; LONG $0; LONG $0; LONG $0;
|
||||||
|
LONG $0; LONG $0; LONG $0; LONG $0;
|
||||||
|
LONG $0; LONG $0; LONG $0; LONG $0;
|
||||||
|
LONG $0; LONG $0; LONG $0; LONG $0;
|
||||||
|
LONG $0; LONG $0; LONG $0; LONG $0;
|
||||||
|
LONG $0; LONG $0; LONG $0; LONG $0;
|
||||||
|
LONG $0; LONG $0; LONG $0; LONG $0;
|
||||||
|
LONG $0; LONG $0; LONG $0; LONG $0
|
||||||
|
|
||||||
|
MODE $64
|
||||||
|
|
||||||
|
TEXT start(SB), 1, $-4
|
||||||
|
/* spill arguments */
|
||||||
|
MOVQ CX, 8(SP)
|
||||||
|
MOVQ DX, 16(SP)
|
||||||
|
|
||||||
|
CALL reloc(SP)
|
||||||
|
|
||||||
|
TEXT reloc(SB), 1, $-4
|
||||||
|
MOVQ 0(SP), SI
|
||||||
|
SUBQ $reloc-IMAGEBASE(SB), SI
|
||||||
|
MOVQ $IMAGEBASE, DI
|
||||||
|
MOVQ $edata-IMAGEBASE(SB), CX
|
||||||
|
CLD
|
||||||
|
REP; MOVSB
|
||||||
|
|
||||||
|
MOVQ 16(SP), BP
|
||||||
|
MOVQ $main(SB), DI
|
||||||
|
MOVQ DI, (SP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT eficall(SB), 1, $-4
|
||||||
|
MOVQ 0(SP), DI /* saved by callee */
|
||||||
|
MOVQ 16(SP), AX
|
||||||
|
ADDQ $24, SP
|
||||||
|
|
||||||
|
/* arguments in regisyers */
|
||||||
|
MOVQ 0(SP), CX
|
||||||
|
MOVQ 8(SP), DX
|
||||||
|
MOVQ 16(SP), R8
|
||||||
|
MOVQ 24(SP), R9
|
||||||
|
|
||||||
|
CALL AX
|
||||||
|
|
||||||
|
SUBQ $24, SP
|
||||||
|
MOVQ DI, 0(SP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
#include "mem.h"
|
||||||
|
|
||||||
|
TEXT jump(SB), 1, $-4
|
||||||
|
CLI
|
||||||
|
|
||||||
|
/* load zero length idt */
|
||||||
|
MOVL $_idtptr64p<>(SB), AX
|
||||||
|
MOVL (AX), IDTR
|
||||||
|
|
||||||
|
/* load temporary gdt */
|
||||||
|
MOVL $_gdtptr64p<>(SB), AX
|
||||||
|
MOVL (AX), GDTR
|
||||||
|
|
||||||
|
/* load CS with 32bit code segment */
|
||||||
|
PUSHQ $SELECTOR(3, SELGDT, 0)
|
||||||
|
PUSHQ $_warp32<>(SB)
|
||||||
|
RETFQ
|
||||||
|
|
||||||
|
MODE $32
|
||||||
|
|
||||||
|
TEXT _warp32<>(SB), 1, $-4
|
||||||
|
|
||||||
|
/* load 32bit data segments */
|
||||||
|
MOVL $SELECTOR(2, SELGDT, 0), AX
|
||||||
|
MOVW AX, DS
|
||||||
|
MOVW AX, ES
|
||||||
|
MOVW AX, FS
|
||||||
|
MOVW AX, GS
|
||||||
|
MOVW AX, SS
|
||||||
|
|
||||||
|
/* turn off paging */
|
||||||
|
MOVL CR0, AX
|
||||||
|
ANDL $0x7fffffff, AX /* ~(PG) */
|
||||||
|
MOVL AX, CR0
|
||||||
|
|
||||||
|
MOVL $0, AX
|
||||||
|
MOVL AX, CR3
|
||||||
|
|
||||||
|
/* disable long mode */
|
||||||
|
MOVL $0xc0000080, CX /* Extended Feature Enable */
|
||||||
|
RDMSR
|
||||||
|
ANDL $0xfffffeff, AX /* Long Mode Disable */
|
||||||
|
WRMSR
|
||||||
|
|
||||||
|
/* diable pae */
|
||||||
|
MOVL CR4, AX
|
||||||
|
ANDL $0xffffff5f, AX /* ~(PAE|PGE) */
|
||||||
|
MOVL AX, CR4
|
||||||
|
|
||||||
|
JMP *BP
|
||||||
|
|
||||||
|
TEXT _gdt<>(SB), 1, $-4
|
||||||
|
/* null descriptor */
|
||||||
|
LONG $0
|
||||||
|
LONG $0
|
||||||
|
|
||||||
|
/* (KESEG) 64 bit long mode exec segment */
|
||||||
|
LONG $(0xFFFF)
|
||||||
|
LONG $(SEGL|SEGG|SEGP|(0xF<<16)|SEGPL(0)|SEGEXEC|SEGR)
|
||||||
|
|
||||||
|
/* 32 bit data segment descriptor for 4 gigabytes (PL 0) */
|
||||||
|
LONG $(0xFFFF)
|
||||||
|
LONG $(SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(0)|SEGDATA|SEGW)
|
||||||
|
|
||||||
|
/* 32 bit exec segment descriptor for 4 gigabytes (PL 0) */
|
||||||
|
LONG $(0xFFFF)
|
||||||
|
LONG $(SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(0)|SEGEXEC|SEGR)
|
||||||
|
|
||||||
|
TEXT _gdtptr64p<>(SB), 1, $-4
|
||||||
|
WORD $(4*8-1)
|
||||||
|
QUAD $_gdt<>(SB)
|
||||||
|
|
||||||
|
TEXT _idtptr64p<>(SB), 1, $-4
|
||||||
|
WORD $0
|
||||||
|
QUAD $0
|
382
sys/src/boot/efi/sub.c
Normal file
382
sys/src/boot/efi/sub.c
Normal file
|
@ -0,0 +1,382 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <a.out.h>
|
||||||
|
#include "fns.h"
|
||||||
|
#include "mem.h"
|
||||||
|
|
||||||
|
char hex[] = "0123456789abcdef";
|
||||||
|
|
||||||
|
void
|
||||||
|
print(char *s)
|
||||||
|
{
|
||||||
|
while(*s != 0){
|
||||||
|
if(*s == '\n')
|
||||||
|
putc('\r');
|
||||||
|
putc(*s++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
readn(void *f, void *data, int len)
|
||||||
|
{
|
||||||
|
uchar *p, *e;
|
||||||
|
|
||||||
|
putc(' ');
|
||||||
|
p = data;
|
||||||
|
e = p + len;
|
||||||
|
while(p < e){
|
||||||
|
if(((ulong)p & 0xF000) == 0){
|
||||||
|
putc('\b');
|
||||||
|
putc(hex[((ulong)p>>16)&0xF]);
|
||||||
|
}
|
||||||
|
if((len = read(f, p, e - p)) <= 0)
|
||||||
|
break;
|
||||||
|
p += len;
|
||||||
|
}
|
||||||
|
putc('\b');
|
||||||
|
|
||||||
|
return p - (uchar*)data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
memmove(void *dst, void *src, int n)
|
||||||
|
{
|
||||||
|
uchar *d = dst;
|
||||||
|
uchar *s = src;
|
||||||
|
|
||||||
|
if(d < s){
|
||||||
|
while(n-- > 0)
|
||||||
|
*d++ = *s++;
|
||||||
|
} else if(d > s){
|
||||||
|
s += n;
|
||||||
|
d += n;
|
||||||
|
while(n-- > 0)
|
||||||
|
*--d = *--s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
memcmp(void *src, void *dst, int n)
|
||||||
|
{
|
||||||
|
uchar *d = dst;
|
||||||
|
uchar *s = src;
|
||||||
|
int r = 0;
|
||||||
|
|
||||||
|
while(n-- > 0){
|
||||||
|
r = *d++ - *s++;
|
||||||
|
if(r != 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
strlen(char *s)
|
||||||
|
{
|
||||||
|
char *p = s;
|
||||||
|
|
||||||
|
while(*p != '\0')
|
||||||
|
p++;
|
||||||
|
|
||||||
|
return p - s;
|
||||||
|
}
|
||||||
|
|
||||||
|
char*
|
||||||
|
strchr(char *s, int c)
|
||||||
|
{
|
||||||
|
for(; *s != 0; s++)
|
||||||
|
if(*s == c)
|
||||||
|
return s;
|
||||||
|
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
memset(void *dst, int v, int n)
|
||||||
|
{
|
||||||
|
uchar *d = dst;
|
||||||
|
|
||||||
|
while(n > 0){
|
||||||
|
*d++ = v;
|
||||||
|
n--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
readline(void *f, char buf[64])
|
||||||
|
{
|
||||||
|
static char white[] = "\t ";
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
p = buf;
|
||||||
|
do{
|
||||||
|
if(f == nil)
|
||||||
|
putc('>');
|
||||||
|
for(;;){
|
||||||
|
if(f == nil){
|
||||||
|
while((*p = getc()) == 0)
|
||||||
|
;
|
||||||
|
putc(*p);
|
||||||
|
if(*p == '\r')
|
||||||
|
putc('\n');
|
||||||
|
else if(*p == '\b' && p > buf){
|
||||||
|
p--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}else if(read(f, p, 1) <= 0)
|
||||||
|
return 0;
|
||||||
|
if(strchr("\r\n", *p) != nil)
|
||||||
|
break;
|
||||||
|
if(p == buf && strchr(white, *p) != nil)
|
||||||
|
continue; /* whitespace on start of line */
|
||||||
|
if(p >= buf + 64-1){
|
||||||
|
if(f == nil){
|
||||||
|
putc('\b');
|
||||||
|
putc(' ');
|
||||||
|
putc('\b');
|
||||||
|
}
|
||||||
|
continue; /* line full do not advance */
|
||||||
|
}
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
while(p > buf && strchr(white, p[-1]))
|
||||||
|
p--;
|
||||||
|
}while(p == buf);
|
||||||
|
*p = 0;
|
||||||
|
|
||||||
|
return p - buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
timeout(int ms)
|
||||||
|
{
|
||||||
|
while(ms > 0){
|
||||||
|
if(getc() != 0)
|
||||||
|
return 1;
|
||||||
|
usleep(100000);
|
||||||
|
ms -= 100;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BOOTLINE ((char*)CONFADDR)
|
||||||
|
#define BOOTLINELEN 64
|
||||||
|
#define BOOTARGS ((char*)(CONFADDR+BOOTLINELEN))
|
||||||
|
#define BOOTARGSLEN (4096-0x200-BOOTLINELEN)
|
||||||
|
|
||||||
|
char *confend;
|
||||||
|
|
||||||
|
static char*
|
||||||
|
getconf(char *s, char *buf)
|
||||||
|
{
|
||||||
|
char *p, *e;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
n = strlen(s);
|
||||||
|
for(p = BOOTARGS; p < confend; p = e+1){
|
||||||
|
for(e = p+1; e < confend; e++)
|
||||||
|
if(*e == '\n')
|
||||||
|
break;
|
||||||
|
if(memcmp(p, s, n) == 0){
|
||||||
|
p += n;
|
||||||
|
n = e - p;
|
||||||
|
buf[n] = 0;
|
||||||
|
memmove(buf, p, n);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
delconf(char *s)
|
||||||
|
{
|
||||||
|
char *p, *e;
|
||||||
|
|
||||||
|
for(p = BOOTARGS; p < confend; p = e){
|
||||||
|
for(e = p+1; e < confend; e++){
|
||||||
|
if(*e == '\n'){
|
||||||
|
e++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(memcmp(p, s, strlen(s)) == 0){
|
||||||
|
memmove(p, e, confend - e);
|
||||||
|
confend -= e - p;
|
||||||
|
*confend = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char*
|
||||||
|
configure(void *f, char *path)
|
||||||
|
{
|
||||||
|
char line[64], *kern, *s, *p;
|
||||||
|
int inblock, nowait, n;
|
||||||
|
static int once = 1;
|
||||||
|
|
||||||
|
if(once){
|
||||||
|
once = 0;
|
||||||
|
Clear:
|
||||||
|
memset(BOOTLINE, 0, BOOTLINELEN);
|
||||||
|
|
||||||
|
confend = BOOTARGS;
|
||||||
|
memset(confend, 0, BOOTARGSLEN);
|
||||||
|
eficonfig(&confend);
|
||||||
|
}
|
||||||
|
nowait = 1;
|
||||||
|
inblock = 0;
|
||||||
|
Loop:
|
||||||
|
while(readline(f, line) > 0){
|
||||||
|
if(*line == 0 || strchr("#;=", *line) != nil)
|
||||||
|
continue;
|
||||||
|
if(*line == '['){
|
||||||
|
inblock = memcmp("[common]", line, 8) != 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(memcmp("boot", line, 5) == 0){
|
||||||
|
nowait=1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(memcmp("wait", line, 5) == 0){
|
||||||
|
nowait=0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(memcmp("show", line, 5) == 0){
|
||||||
|
print(BOOTARGS);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(memcmp("clear", line, 5) == 0){
|
||||||
|
if(line[5] == '\0'){
|
||||||
|
print("ok\n");
|
||||||
|
goto Clear;
|
||||||
|
} else if(line[5] == ' ' && delconf(line+6))
|
||||||
|
print("ok\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(inblock != 0 || (p = strchr(line, '=')) == nil)
|
||||||
|
continue;
|
||||||
|
*p++ = 0;
|
||||||
|
delconf(line);
|
||||||
|
s = confend;
|
||||||
|
memmove(confend, line, n = strlen(line)); confend += n;
|
||||||
|
*confend++ = '=';
|
||||||
|
memmove(confend, p, n = strlen(p)); confend += n;
|
||||||
|
*confend++ = '\n';
|
||||||
|
*confend = 0;
|
||||||
|
print(s);
|
||||||
|
}
|
||||||
|
kern = getconf("bootfile=", path);
|
||||||
|
|
||||||
|
if(f != nil){
|
||||||
|
close(f);
|
||||||
|
f = nil;
|
||||||
|
|
||||||
|
if(kern != nil && (nowait==0 || timeout(1000)))
|
||||||
|
goto Loop;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(kern == nil){
|
||||||
|
print("no bootfile\n");
|
||||||
|
goto Loop;
|
||||||
|
}
|
||||||
|
while((p = strchr(kern, '!')) != nil)
|
||||||
|
kern = p+1;
|
||||||
|
|
||||||
|
return kern;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char*
|
||||||
|
numfmt(char *s, ulong b, ulong i, ulong a)
|
||||||
|
{
|
||||||
|
char *r;
|
||||||
|
|
||||||
|
if(i == 0){
|
||||||
|
ulong v = a;
|
||||||
|
while(v != 0){
|
||||||
|
v /= b;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if(i == 0)
|
||||||
|
i = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
s += i;
|
||||||
|
r = s;
|
||||||
|
while(i > 0){
|
||||||
|
*--s = hex[a % b];
|
||||||
|
a /= b;
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
char*
|
||||||
|
hexfmt(char *s, int i, uvlong a)
|
||||||
|
{
|
||||||
|
if(i > 8){
|
||||||
|
s = numfmt(s, 16, i-8, a>>32);
|
||||||
|
i = 8;
|
||||||
|
}
|
||||||
|
return numfmt(s, 16, i, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
char*
|
||||||
|
decfmt(char *s, int i, ulong a)
|
||||||
|
{
|
||||||
|
return numfmt(s, 10, i, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ulong
|
||||||
|
beswal(ulong l)
|
||||||
|
{
|
||||||
|
uchar *p = (uchar*)&l;
|
||||||
|
return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
char*
|
||||||
|
bootkern(void *f)
|
||||||
|
{
|
||||||
|
uchar *e, *d, *t;
|
||||||
|
ulong n;
|
||||||
|
Exec ex;
|
||||||
|
|
||||||
|
if(readn(f, &ex, sizeof(ex)) != sizeof(ex))
|
||||||
|
return "bad header";
|
||||||
|
|
||||||
|
e = (uchar*)(beswal(ex.entry) & ~0xF0000000UL);
|
||||||
|
switch(beswal(ex.magic)){
|
||||||
|
case S_MAGIC:
|
||||||
|
if(readn(f, e, 8) != 8)
|
||||||
|
goto Error;
|
||||||
|
case I_MAGIC:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return "bad magic";
|
||||||
|
}
|
||||||
|
|
||||||
|
t = e;
|
||||||
|
n = beswal(ex.text);
|
||||||
|
if(readn(f, t, n) != n)
|
||||||
|
goto Error;
|
||||||
|
t += n;
|
||||||
|
d = (uchar*)PGROUND((ulong)t);
|
||||||
|
memset(t, 0, d - t);
|
||||||
|
n = beswal(ex.data);
|
||||||
|
if(readn(f, d, n) != n)
|
||||||
|
goto Error;
|
||||||
|
d += n;
|
||||||
|
t = (uchar*)PGROUND((ulong)d);
|
||||||
|
t += PGROUND(beswal(ex.bss));
|
||||||
|
memset(d, 0, t - d);
|
||||||
|
|
||||||
|
close(f);
|
||||||
|
unload();
|
||||||
|
|
||||||
|
jump(e);
|
||||||
|
|
||||||
|
Error:
|
||||||
|
return "i/o error";
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue