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…
Reference in a new issue