efi: add initial pxe support (v4 only)
This commit is contained in:
parent
e81e1a4aed
commit
16e08adb32
8 changed files with 555 additions and 148 deletions
|
@ -2,14 +2,13 @@
|
||||||
#include "fns.h"
|
#include "fns.h"
|
||||||
#include "efi.h"
|
#include "efi.h"
|
||||||
|
|
||||||
enum {
|
|
||||||
MAXPATH = 128,
|
|
||||||
};
|
|
||||||
|
|
||||||
UINTN MK;
|
UINTN MK;
|
||||||
EFI_HANDLE IH;
|
EFI_HANDLE IH;
|
||||||
EFI_SYSTEM_TABLE *ST;
|
EFI_SYSTEM_TABLE *ST;
|
||||||
EFI_FILE_PROTOCOL *root;
|
|
||||||
|
void* (*open)(char *name);
|
||||||
|
int (*read)(void *f, void *data, int len);
|
||||||
|
void (*close)(void *f);
|
||||||
|
|
||||||
void
|
void
|
||||||
putc(int c)
|
putc(int c)
|
||||||
|
@ -18,7 +17,7 @@ putc(int c)
|
||||||
|
|
||||||
w[0] = c;
|
w[0] = c;
|
||||||
w[1] = 0;
|
w[1] = 0;
|
||||||
eficall(2, ST->ConOut->OutputString, ST->ConOut, w);
|
eficall(ST->ConOut->OutputString, ST->ConOut, w);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -26,7 +25,7 @@ getc(void)
|
||||||
{
|
{
|
||||||
EFI_INPUT_KEY k;
|
EFI_INPUT_KEY k;
|
||||||
|
|
||||||
if(eficall(2, ST->ConIn->ReadKeyStroke, ST->ConIn, &k))
|
if(eficall(ST->ConIn->ReadKeyStroke, ST->ConIn, &k))
|
||||||
return 0;
|
return 0;
|
||||||
return k.UnicodeChar;
|
return k.UnicodeChar;
|
||||||
}
|
}
|
||||||
|
@ -34,78 +33,15 @@ getc(void)
|
||||||
void
|
void
|
||||||
usleep(int us)
|
usleep(int us)
|
||||||
{
|
{
|
||||||
eficall(1, ST->BootServices->Stall, (UINTN)us);
|
eficall(ST->BootServices->Stall, (UINTN)us);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
unload(void)
|
unload(void)
|
||||||
{
|
{
|
||||||
eficall(2, ST->BootServices->ExitBootServices, IH, MK);
|
eficall(ST->BootServices->ExitBootServices, IH, MK);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
fsinit(void)
|
|
||||||
{
|
|
||||||
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *fs;
|
|
||||||
|
|
||||||
fs = nil;
|
|
||||||
root = nil;
|
|
||||||
if(eficall(3, ST->BootServices->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
|
static void
|
||||||
memconf(char **cfg)
|
memconf(char **cfg)
|
||||||
{
|
{
|
||||||
|
@ -134,7 +70,7 @@ memconf(char **cfg)
|
||||||
mapsize = sizeof(mapbuf);
|
mapsize = sizeof(mapbuf);
|
||||||
entsize = sizeof(EFI_MEMORY_DESCRIPTOR);
|
entsize = sizeof(EFI_MEMORY_DESCRIPTOR);
|
||||||
entvers = 1;
|
entvers = 1;
|
||||||
if(eficall(5, ST->BootServices->GetMemoryMap, &mapsize, mapbuf, &MK, &entsize, &entvers))
|
if(eficall(ST->BootServices->GetMemoryMap, &mapsize, mapbuf, &MK, &entsize, &entvers))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
s = *cfg;
|
s = *cfg;
|
||||||
|
@ -165,6 +101,16 @@ memconf(char **cfg)
|
||||||
static void
|
static void
|
||||||
acpiconf(char **cfg)
|
acpiconf(char **cfg)
|
||||||
{
|
{
|
||||||
|
static EFI_GUID ACPI_20_TABLE_GUID = {
|
||||||
|
0x8868e871, 0xe4f1, 0x11d3,
|
||||||
|
0xbc, 0x22, 0x00, 0x80,
|
||||||
|
0xc7, 0x3c, 0x88, 0x81,
|
||||||
|
};
|
||||||
|
static EFI_GUID ACPI_10_TABLE_GUID = {
|
||||||
|
0xeb9d2d30, 0x2d88, 0x11d3,
|
||||||
|
0x9a, 0x16, 0x00, 0x90,
|
||||||
|
0x27, 0x3f, 0xc1, 0x4d,
|
||||||
|
};
|
||||||
EFI_CONFIGURATION_TABLE *t;
|
EFI_CONFIGURATION_TABLE *t;
|
||||||
uintptr pa;
|
uintptr pa;
|
||||||
char *s;
|
char *s;
|
||||||
|
@ -220,6 +166,11 @@ lowbit(ulong mask)
|
||||||
static void
|
static void
|
||||||
screenconf(char **cfg)
|
screenconf(char **cfg)
|
||||||
{
|
{
|
||||||
|
static EFI_GUID EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID = {
|
||||||
|
0x9042a9de, 0x23dc, 0x4a38,
|
||||||
|
0x96, 0xfb, 0x7a, 0xde,
|
||||||
|
0xd0, 0x80, 0x51, 0x6a,
|
||||||
|
};
|
||||||
EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
|
EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
|
||||||
EFI_HANDLE *Handles;
|
EFI_HANDLE *Handles;
|
||||||
UINTN Count;
|
UINTN Count;
|
||||||
|
@ -231,13 +182,13 @@ screenconf(char **cfg)
|
||||||
|
|
||||||
Count = 0;
|
Count = 0;
|
||||||
Handles = nil;
|
Handles = nil;
|
||||||
if(eficall(5, ST->BootServices->LocateHandleBuffer,
|
if(eficall(ST->BootServices->LocateHandleBuffer,
|
||||||
ByProtocol, &EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID, nil, &Count, &Handles))
|
ByProtocol, &EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID, nil, &Count, &Handles))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for(i=0; i<Count; i++){
|
for(i=0; i<Count; i++){
|
||||||
gop = nil;
|
gop = nil;
|
||||||
if(eficall(3, ST->BootServices->HandleProtocol,
|
if(eficall(ST->BootServices->HandleProtocol,
|
||||||
Handles[i], &EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID, &gop))
|
Handles[i], &EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID, &gop))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -331,7 +282,7 @@ eficonfig(char **cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
main(EFI_HANDLE ih, EFI_SYSTEM_TABLE *st)
|
efimain(EFI_HANDLE ih, EFI_SYSTEM_TABLE *st)
|
||||||
{
|
{
|
||||||
char path[MAXPATH], *kern;
|
char path[MAXPATH], *kern;
|
||||||
void *f;
|
void *f;
|
||||||
|
@ -339,12 +290,13 @@ main(EFI_HANDLE ih, EFI_SYSTEM_TABLE *st)
|
||||||
IH = ih;
|
IH = ih;
|
||||||
ST = st;
|
ST = st;
|
||||||
|
|
||||||
fsinit();
|
f = pxeinit();
|
||||||
|
if(f == nil)
|
||||||
|
f = fsinit();
|
||||||
|
|
||||||
f = fswalk(root, "/plan9.ini");
|
|
||||||
for(;;){
|
for(;;){
|
||||||
kern = configure(f, path);
|
kern = configure(f, path);
|
||||||
f = fswalk(root, kern);
|
f = open(kern);
|
||||||
if(f == nil){
|
if(f == nil){
|
||||||
print("not found\n");
|
print("not found\n");
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -4,6 +4,7 @@ typedef uchar UINT8;
|
||||||
typedef ushort UINT16;
|
typedef ushort UINT16;
|
||||||
typedef ulong UINT32;
|
typedef ulong UINT32;
|
||||||
typedef uvlong UINT64;
|
typedef uvlong UINT64;
|
||||||
|
typedef UINT8 BOOLEAN;
|
||||||
|
|
||||||
typedef uintptr UINTN;
|
typedef uintptr UINTN;
|
||||||
|
|
||||||
|
@ -87,41 +88,6 @@ typedef struct {
|
||||||
EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode;
|
EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode;
|
||||||
} EFI_GRAPHICS_OUTPUT_PROTOCOL;
|
} 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 {
|
enum {
|
||||||
EfiReservedMemoryType,
|
EfiReservedMemoryType,
|
||||||
EfiLoaderCode,
|
EfiLoaderCode,
|
||||||
|
@ -243,19 +209,6 @@ typedef struct {
|
||||||
void *QueryVariableInfo;
|
void *QueryVariableInfo;
|
||||||
} EFI_RUNTIME_SERVICES;
|
} 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 {
|
typedef struct {
|
||||||
EFI_GUID VendorGuid;
|
EFI_GUID VendorGuid;
|
||||||
void *VendorTable;
|
void *VendorTable;
|
||||||
|
@ -282,3 +235,6 @@ typedef struct {
|
||||||
UINTN NumberOfTableEntries;
|
UINTN NumberOfTableEntries;
|
||||||
EFI_CONFIGURATION_TABLE *ConfigurationTable;
|
EFI_CONFIGURATION_TABLE *ConfigurationTable;
|
||||||
} EFI_SYSTEM_TABLE;
|
} EFI_SYSTEM_TABLE;
|
||||||
|
|
||||||
|
extern EFI_SYSTEM_TABLE *ST;
|
||||||
|
extern EFI_HANDLE IH;
|
||||||
|
|
|
@ -1,11 +1,20 @@
|
||||||
|
enum {
|
||||||
|
MAXPATH = 128,
|
||||||
|
};
|
||||||
|
|
||||||
extern char hex[];
|
extern char hex[];
|
||||||
|
|
||||||
void usleep(int t);
|
void usleep(int t);
|
||||||
void jump(void *pc);
|
void jump(void *pc);
|
||||||
|
|
||||||
int read(void *f, void *data, int len);
|
void* pxeinit(void);
|
||||||
|
void* fsinit(void);
|
||||||
|
|
||||||
|
void* (*open)(char *name);
|
||||||
|
int (*read)(void *f, void *data, int len);
|
||||||
|
void (*close)(void *f);
|
||||||
|
|
||||||
int readn(void *f, void *data, int len);
|
int readn(void *f, void *data, int len);
|
||||||
void close(void *f);
|
|
||||||
void unload(void);
|
void unload(void);
|
||||||
|
|
||||||
int getc(void);
|
int getc(void);
|
||||||
|
@ -25,5 +34,5 @@ char *bootkern(void *f);
|
||||||
char *hexfmt(char *s, int i, uvlong a);
|
char *hexfmt(char *s, int i, uvlong a);
|
||||||
char *decfmt(char *s, int i, ulong a);
|
char *decfmt(char *s, int i, ulong a);
|
||||||
|
|
||||||
long eficall(long narg, void *proc, ...);
|
uintptr eficall(void *proc, ...);
|
||||||
void eficonfig(char **cfg);
|
void eficonfig(char **cfg);
|
||||||
|
|
106
sys/src/boot/efi/fs.c
Normal file
106
sys/src/boot/efi/fs.c
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include "fns.h"
|
||||||
|
#include "efi.h"
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
static
|
||||||
|
EFI_GUID EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID = {
|
||||||
|
0x0964e5b22, 0x6459, 0x11d2,
|
||||||
|
0x8e, 0x39, 0x00, 0xa0,
|
||||||
|
0xc9, 0x69, 0x72, 0x3b,
|
||||||
|
};
|
||||||
|
|
||||||
|
static
|
||||||
|
EFI_FILE_PROTOCOL *fsroot;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void*
|
||||||
|
fsopen(char *name)
|
||||||
|
{
|
||||||
|
CHAR16 wname[MAXPATH];
|
||||||
|
EFI_FILE_PROTOCOL *fp;
|
||||||
|
|
||||||
|
if(fsroot == nil)
|
||||||
|
return nil;
|
||||||
|
|
||||||
|
towpath(wname, MAXPATH, name);
|
||||||
|
|
||||||
|
fp = nil;
|
||||||
|
if(eficall(fsroot->Open, fsroot, &fp, wname, (UINT64)1, (UINT64)1))
|
||||||
|
return nil;
|
||||||
|
return fp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
fsread(void *f, void *data, int len)
|
||||||
|
{
|
||||||
|
UINTN size;
|
||||||
|
|
||||||
|
size = len;
|
||||||
|
if(eficall(((EFI_FILE_PROTOCOL*)f)->Read, f, &size, data))
|
||||||
|
return 0;
|
||||||
|
return (int)size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fsclose(void *f)
|
||||||
|
{
|
||||||
|
eficall(((EFI_FILE_PROTOCOL*)f)->Close, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void*
|
||||||
|
fsinit(void)
|
||||||
|
{
|
||||||
|
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *fs;
|
||||||
|
|
||||||
|
fs = nil;
|
||||||
|
fsroot = nil;
|
||||||
|
if(eficall(ST->BootServices->LocateProtocol,
|
||||||
|
&EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID, nil, &fs))
|
||||||
|
return nil;
|
||||||
|
if(eficall(fs->OpenVolume, fs, &fsroot)){
|
||||||
|
fsroot = nil;
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
read = fsread;
|
||||||
|
close = fsclose;
|
||||||
|
open = fsopen;
|
||||||
|
|
||||||
|
return fsopen("/plan9.ini");
|
||||||
|
}
|
|
@ -13,7 +13,7 @@ install:V: $TARG
|
||||||
clean:V:
|
clean:V:
|
||||||
rm -f *.[68] *.out $TARG
|
rm -f *.[68] *.out $TARG
|
||||||
|
|
||||||
bootia32.efi: pe32.8 efi.8 sub.8
|
bootia32.efi: pe32.8 efi.8 fs.8 pxe.8 sub.8
|
||||||
8l -l -H3 -T$IMAGEBASE -o $target $prereq
|
8l -l -H3 -T$IMAGEBASE -o $target $prereq
|
||||||
|
|
||||||
pe32.8: pe32.s
|
pe32.8: pe32.s
|
||||||
|
@ -22,13 +22,19 @@ pe32.8: pe32.s
|
||||||
efi.8: efi.c efi.h
|
efi.8: efi.c efi.h
|
||||||
8c $CFLAGS efi.c
|
8c $CFLAGS efi.c
|
||||||
|
|
||||||
|
fs.8: fs.c efi.h
|
||||||
|
8c $CFLAGS fs.c
|
||||||
|
|
||||||
|
pxe.8: pxe.c efi.h
|
||||||
|
8c $CFLAGS pxe.c
|
||||||
|
|
||||||
sub.8: sub.c
|
sub.8: sub.c
|
||||||
8c $CFLAGS sub.c
|
8c $CFLAGS sub.c
|
||||||
|
|
||||||
%.8: $HFILES
|
%.8: $HFILES
|
||||||
|
|
||||||
|
|
||||||
bootx64.efi: pe64.6 efi.6 sub.6
|
bootx64.efi: pe64.6 efi.6 fs.6 pxe.6 sub.6
|
||||||
6l -l -s -R1 -T$IMAGEBASE -o bootx64.out $prereq
|
6l -l -s -R1 -T$IMAGEBASE -o bootx64.out $prereq
|
||||||
dd -if bootx64.out -bs 1 -iseek 40 >$target
|
dd -if bootx64.out -bs 1 -iseek 40 >$target
|
||||||
|
|
||||||
|
@ -38,6 +44,12 @@ pe64.6: pe64.s
|
||||||
efi.6: efi.c efi.h
|
efi.6: efi.c efi.h
|
||||||
6c $CFLAGS efi.c
|
6c $CFLAGS efi.c
|
||||||
|
|
||||||
|
fs.6: fs.c efi.h
|
||||||
|
6c $CFLAGS fs.c
|
||||||
|
|
||||||
|
pxe.6: pxe.c efi.h
|
||||||
|
6c $CFLAGS pxe.c
|
||||||
|
|
||||||
sub.6: sub.c
|
sub.6: sub.c
|
||||||
6c $CFLAGS sub.c
|
6c $CFLAGS sub.c
|
||||||
|
|
||||||
|
|
|
@ -129,7 +129,7 @@ TEXT reloc(SB), 1, $0
|
||||||
MOVL $edata-IMAGEBASE(SB), CX
|
MOVL $edata-IMAGEBASE(SB), CX
|
||||||
CLD
|
CLD
|
||||||
REP; MOVSB
|
REP; MOVSB
|
||||||
MOVL $main(SB), DI
|
MOVL $efimain(SB), DI
|
||||||
MOVL DI, (SP)
|
MOVL DI, (SP)
|
||||||
RET
|
RET
|
||||||
|
|
||||||
|
@ -138,12 +138,22 @@ TEXT jump(SB), $0
|
||||||
MOVL 4(SP), AX
|
MOVL 4(SP), AX
|
||||||
JMP *AX
|
JMP *AX
|
||||||
|
|
||||||
|
|
||||||
TEXT eficall(SB), 1, $0
|
TEXT eficall(SB), 1, $0
|
||||||
MOVL 0(SP), DI /* saved by callee */
|
MOVL SP, SI
|
||||||
MOVL 8(SP), AX
|
MOVL SP, DI
|
||||||
ADDL $12, SP
|
MOVL $(4*16), CX
|
||||||
|
SUBL CX, DI
|
||||||
|
ANDL $~15ULL, DI
|
||||||
|
SUBL $8, DI
|
||||||
|
|
||||||
|
MOVL 4(SI), AX
|
||||||
|
LEAL 8(DI), SP
|
||||||
|
|
||||||
|
CLD
|
||||||
|
REP; MOVSB
|
||||||
|
SUBL $(4*16), SI
|
||||||
|
|
||||||
CALL AX
|
CALL AX
|
||||||
SUBL $12, SP
|
|
||||||
MOVL DI, 0(SP)
|
MOVL SI, SP
|
||||||
RET
|
RET
|
||||||
|
|
|
@ -136,25 +136,28 @@ TEXT reloc(SB), 1, $-4
|
||||||
REP; MOVSB
|
REP; MOVSB
|
||||||
|
|
||||||
MOVQ 16(SP), BP
|
MOVQ 16(SP), BP
|
||||||
MOVQ $main(SB), DI
|
MOVQ $efimain(SB), DI
|
||||||
MOVQ DI, (SP)
|
MOVQ DI, (SP)
|
||||||
RET
|
RET
|
||||||
|
|
||||||
TEXT eficall(SB), 1, $-4
|
TEXT eficall(SB), 1, $-4
|
||||||
MOVQ 0(SP), DI /* saved by callee */
|
MOVQ SP, SI
|
||||||
MOVQ 16(SP), AX
|
MOVQ SP, DI
|
||||||
ADDQ $24, SP
|
MOVL $(8*16), CX
|
||||||
|
SUBQ CX, DI
|
||||||
|
ANDQ $~15ULL, DI
|
||||||
|
LEAQ 16(DI), SP
|
||||||
|
CLD
|
||||||
|
REP; MOVSB
|
||||||
|
SUBQ $(8*16), SI
|
||||||
|
|
||||||
/* arguments in regisyers */
|
|
||||||
MOVQ 0(SP), CX
|
MOVQ 0(SP), CX
|
||||||
MOVQ 8(SP), DX
|
MOVQ 8(SP), DX
|
||||||
MOVQ 16(SP), R8
|
MOVQ 16(SP), R8
|
||||||
MOVQ 24(SP), R9
|
MOVQ 24(SP), R9
|
||||||
|
CALL BP
|
||||||
|
|
||||||
CALL AX
|
MOVQ SI, SP
|
||||||
|
|
||||||
SUBQ $24, SP
|
|
||||||
MOVQ DI, 0(SP)
|
|
||||||
RET
|
RET
|
||||||
|
|
||||||
#include "mem.h"
|
#include "mem.h"
|
||||||
|
|
359
sys/src/boot/efi/pxe.c
Normal file
359
sys/src/boot/efi/pxe.c
Normal file
|
@ -0,0 +1,359 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include "fns.h"
|
||||||
|
#include "efi.h"
|
||||||
|
|
||||||
|
typedef UINT16 EFI_PXE_BASE_CODE_UDP_PORT;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT8 Addr[4];
|
||||||
|
} EFI_IPv4_ADDRESS;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT8 Addr[16];
|
||||||
|
} EFI_IPv6_ADDRESS;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
UINT32 Addr[4];
|
||||||
|
EFI_IPv4_ADDRESS v4;
|
||||||
|
EFI_IPv6_ADDRESS v6;
|
||||||
|
} EFI_IP_ADDRESS;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT8 Addr[32];
|
||||||
|
} EFI_MAC_ADDRESS;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT8 BootpOpcode;
|
||||||
|
UINT8 BootpHwType;
|
||||||
|
UINT8 BootpHwAddrLen;
|
||||||
|
UINT8 BootpGateHops;
|
||||||
|
UINT32 BootpIdent;
|
||||||
|
UINT16 BootpSeconds;
|
||||||
|
UINT16 BootpFlags;
|
||||||
|
UINT8 BootpCiAddr[4];
|
||||||
|
UINT8 BootpYiAddr[4];
|
||||||
|
UINT8 BootpSiAddr[4];
|
||||||
|
UINT8 BootpGiAddr[4];
|
||||||
|
UINT8 BootpHwAddr[16];
|
||||||
|
UINT8 BootpSrvName[64];
|
||||||
|
UINT8 BootpBootFile[128];
|
||||||
|
UINT32 DhcpMagik;
|
||||||
|
UINT8 DhcpOptions[56];
|
||||||
|
} EFI_PXE_BASE_CODE_DHCPV4_PACKET;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
BOOLEAN Started;
|
||||||
|
BOOLEAN Ipv6Available;
|
||||||
|
BOOLEAN Ipv6Supported;
|
||||||
|
BOOLEAN UsingIpv6;
|
||||||
|
BOOLEAN BisSupported;
|
||||||
|
BOOLEAN BisDetected;
|
||||||
|
BOOLEAN AutoArp;
|
||||||
|
BOOLEAN SendGUID;
|
||||||
|
BOOLEAN DhcpDiscoverValid;
|
||||||
|
BOOLEAN DhcpAckReceived;
|
||||||
|
BOOLEAN ProxyOfferReceived;
|
||||||
|
BOOLEAN PxeDiscoverValid;
|
||||||
|
BOOLEAN PxeReplyReceived;
|
||||||
|
BOOLEAN PxeBisReplyReceived;
|
||||||
|
BOOLEAN IcmpErrorReceived;
|
||||||
|
BOOLEAN TftpErrorReceived;
|
||||||
|
BOOLEAN MakeCallbacks;
|
||||||
|
|
||||||
|
UINT8 TTL;
|
||||||
|
UINT8 ToS;
|
||||||
|
|
||||||
|
UINT8 Reserved;
|
||||||
|
|
||||||
|
UINT8 StationIp[16];
|
||||||
|
UINT8 SubnetMask[16];
|
||||||
|
|
||||||
|
UINT8 DhcpDiscover[1472];
|
||||||
|
UINT8 DhcpAck[1472];
|
||||||
|
} EFI_PXE_BASE_CODE_MODE;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UINT64 Revision;
|
||||||
|
void *Start;
|
||||||
|
void *Stop;
|
||||||
|
void *Dhcp;
|
||||||
|
void *Discover;
|
||||||
|
void *Mtftp;
|
||||||
|
void *UdpWrite;
|
||||||
|
void *UdpRead;
|
||||||
|
void *SetIpFilter;
|
||||||
|
void *Arp;
|
||||||
|
void *SetParameters;
|
||||||
|
void *SetStationIp;
|
||||||
|
void *SetPackets;
|
||||||
|
EFI_PXE_BASE_CODE_MODE *Mode;
|
||||||
|
} EFI_PXE_BASE_CODE_PROTOCOL;
|
||||||
|
|
||||||
|
|
||||||
|
enum {
|
||||||
|
Tftp_READ = 1,
|
||||||
|
Tftp_WRITE = 2,
|
||||||
|
Tftp_DATA = 3,
|
||||||
|
Tftp_ACK = 4,
|
||||||
|
Tftp_ERROR = 5,
|
||||||
|
Tftp_OACK = 6,
|
||||||
|
|
||||||
|
TftpPort = 69,
|
||||||
|
|
||||||
|
Segsize = 512,
|
||||||
|
};
|
||||||
|
|
||||||
|
static
|
||||||
|
EFI_GUID EFI_PXE_BASE_CODE_PROTOCOL_GUID = {
|
||||||
|
0x03C4E603, 0xAC28, 0x11D3,
|
||||||
|
0x9A, 0x2D, 0x00, 0x90,
|
||||||
|
0x27, 0x3F, 0xC1, 0x4D,
|
||||||
|
};
|
||||||
|
|
||||||
|
static
|
||||||
|
EFI_PXE_BASE_CODE_PROTOCOL *pxe;
|
||||||
|
|
||||||
|
static
|
||||||
|
EFI_PXE_BASE_CODE_DHCPV4_PACKET *dhcp;
|
||||||
|
|
||||||
|
typedef struct Tftp Tftp;
|
||||||
|
struct Tftp
|
||||||
|
{
|
||||||
|
EFI_IP_ADDRESS sip;
|
||||||
|
EFI_IP_ADDRESS dip;
|
||||||
|
|
||||||
|
EFI_PXE_BASE_CODE_UDP_PORT sport;
|
||||||
|
EFI_PXE_BASE_CODE_UDP_PORT dport;
|
||||||
|
|
||||||
|
char *rp;
|
||||||
|
char *ep;
|
||||||
|
|
||||||
|
int seq;
|
||||||
|
int eof;
|
||||||
|
|
||||||
|
char pkt[2+2+Segsize];
|
||||||
|
char nul;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
puts(void *x, ushort v)
|
||||||
|
{
|
||||||
|
uchar *p = x;
|
||||||
|
|
||||||
|
p[1] = (v>>8) & 0xFF;
|
||||||
|
p[0] = v & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ushort
|
||||||
|
gets(void *x)
|
||||||
|
{
|
||||||
|
uchar *p = x;
|
||||||
|
|
||||||
|
return p[1]<<8 | p[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
hnputs(void *x, ushort v)
|
||||||
|
{
|
||||||
|
uchar *p = x;
|
||||||
|
|
||||||
|
p[0] = (v>>8) & 0xFF;
|
||||||
|
p[1] = v & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ushort
|
||||||
|
nhgets(void *x)
|
||||||
|
{
|
||||||
|
uchar *p = x;
|
||||||
|
|
||||||
|
return p[0]<<8 | p[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
enum {
|
||||||
|
ANY_SRC_IP = 0x0001,
|
||||||
|
ANY_SRC_PORT = 0x0002,
|
||||||
|
ANY_DEST_IP = 0x0004,
|
||||||
|
ANY_DEST_PORT = 0x0008,
|
||||||
|
USE_FILTER = 0x0010,
|
||||||
|
MAY_FRAGMENT = 0x0020,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
udpread(EFI_IP_ADDRESS *sip, EFI_IP_ADDRESS *dip,
|
||||||
|
EFI_PXE_BASE_CODE_UDP_PORT *sport,
|
||||||
|
EFI_PXE_BASE_CODE_UDP_PORT dport,
|
||||||
|
int *len, void *data)
|
||||||
|
{
|
||||||
|
UINTN size;
|
||||||
|
|
||||||
|
size = *len;
|
||||||
|
if(eficall(pxe->UdpRead, pxe, (UINTN)ANY_SRC_PORT, dip, &dport, sip, sport, nil, nil, &size, data))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
*len = size;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
udpwrite(EFI_IP_ADDRESS *dip,
|
||||||
|
EFI_PXE_BASE_CODE_UDP_PORT sport,
|
||||||
|
EFI_PXE_BASE_CODE_UDP_PORT dport,
|
||||||
|
int len, void *data)
|
||||||
|
{
|
||||||
|
UINTN size;
|
||||||
|
|
||||||
|
size = len;
|
||||||
|
if(eficall(pxe->UdpWrite, pxe, (UINTN)MAY_FRAGMENT, dip, &dport, nil, nil, &sport, nil, nil, &size, data))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
pxeread(void *f, void *data, int len)
|
||||||
|
{
|
||||||
|
Tftp *t = f;
|
||||||
|
int seq, n;
|
||||||
|
|
||||||
|
while(!t->eof && t->rp >= t->ep){
|
||||||
|
for(;;){
|
||||||
|
n = sizeof(t->pkt);
|
||||||
|
if(udpread(&t->dip, &t->sip, &t->dport, t->sport, &n, t->pkt))
|
||||||
|
continue;
|
||||||
|
if(n >= 4)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch(nhgets(t->pkt)){
|
||||||
|
case Tftp_DATA:
|
||||||
|
seq = nhgets(t->pkt+2);
|
||||||
|
if(seq > t->seq){
|
||||||
|
putc('?');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
hnputs(t->pkt, Tftp_ACK);
|
||||||
|
while(udpwrite(&t->dip, t->sport, t->dport, 4, t->pkt))
|
||||||
|
putc('!');
|
||||||
|
if(seq < t->seq){
|
||||||
|
putc('@');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
t->seq = seq+1;
|
||||||
|
n -= 4;
|
||||||
|
t->rp = t->pkt + 4;
|
||||||
|
t->ep = t->rp + n;
|
||||||
|
t->eof = n < Segsize;
|
||||||
|
break;
|
||||||
|
case Tftp_ERROR:
|
||||||
|
print(t->pkt+4);
|
||||||
|
print("\n");
|
||||||
|
default:
|
||||||
|
t->eof = 1;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
n = t->ep - t->rp;
|
||||||
|
if(len > n)
|
||||||
|
len = n;
|
||||||
|
memmove(data, t->rp, len);
|
||||||
|
t->rp += len;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pxeclose(void *f)
|
||||||
|
{
|
||||||
|
Tftp *t = f;
|
||||||
|
t->eof = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
tftpopen(Tftp *t, char *path)
|
||||||
|
{
|
||||||
|
static EFI_PXE_BASE_CODE_UDP_PORT xport = 6666;
|
||||||
|
int r, n;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
t->sport = xport++;
|
||||||
|
t->dport = 0;
|
||||||
|
t->rp = t->ep = 0;
|
||||||
|
t->seq = 1;
|
||||||
|
t->eof = 0;
|
||||||
|
t->nul = 0;
|
||||||
|
p = t->pkt;
|
||||||
|
hnputs(p, Tftp_READ); p += 2;
|
||||||
|
n = strlen(path)+1;
|
||||||
|
memmove(p, path, n); p += n;
|
||||||
|
memmove(p, "octet", 6); p += 6;
|
||||||
|
n = p - t->pkt;
|
||||||
|
for(;;){
|
||||||
|
if(r = udpwrite(&t->dip, t->sport, TftpPort, n, t->pkt))
|
||||||
|
break;
|
||||||
|
if(r = pxeread(t, 0, 0))
|
||||||
|
break;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
pxeclose(t);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void*
|
||||||
|
pxeopen(char *name)
|
||||||
|
{
|
||||||
|
static Tftp t[1];
|
||||||
|
|
||||||
|
memset(t, 0, sizeof(Tftp));
|
||||||
|
|
||||||
|
memmove(&t->dip, dhcp->BootpSiAddr, 4);
|
||||||
|
memmove(&t->sip, pxe->Mode->StationIp, 4);
|
||||||
|
|
||||||
|
if(tftpopen(t, name) == 0)
|
||||||
|
return t;
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
void*
|
||||||
|
pxeinit(void)
|
||||||
|
{
|
||||||
|
EFI_HANDLE *Handles;
|
||||||
|
UINTN Count;
|
||||||
|
char ini[24];
|
||||||
|
uchar *mac;
|
||||||
|
void *f;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
pxe = nil;
|
||||||
|
dhcp = nil;
|
||||||
|
Count = 0;
|
||||||
|
Handles = nil;
|
||||||
|
if(eficall(ST->BootServices->LocateHandleBuffer,
|
||||||
|
ByProtocol, &EFI_PXE_BASE_CODE_PROTOCOL_GUID, nil, &Count, &Handles))
|
||||||
|
return nil;
|
||||||
|
|
||||||
|
for(i=0; i<Count; i++){
|
||||||
|
pxe = nil;
|
||||||
|
if(eficall(ST->BootServices->HandleProtocol,
|
||||||
|
Handles[i], &EFI_PXE_BASE_CODE_PROTOCOL_GUID, &pxe))
|
||||||
|
continue;
|
||||||
|
if(pxe->Mode != nil && pxe->Mode->Started)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dhcp = (EFI_PXE_BASE_CODE_DHCPV4_PACKET*)pxe->Mode->DhcpAck;
|
||||||
|
|
||||||
|
mac = dhcp->BootpHwAddr;
|
||||||
|
memmove(ini, "/cfg/pxe/", 9);
|
||||||
|
for(i=0; i<6; i++){
|
||||||
|
ini[9+i*2+0] = hex[mac[i] >> 4];
|
||||||
|
ini[9+i*2+1] = hex[mac[i] & 0xF];
|
||||||
|
}
|
||||||
|
ini[9+12] = '\0';
|
||||||
|
|
||||||
|
open = pxeopen;
|
||||||
|
read = pxeread;
|
||||||
|
close = pxeclose;
|
||||||
|
|
||||||
|
if((f = pxeopen(ini)) != nil)
|
||||||
|
return f;
|
||||||
|
return pxeopen("/cfg/pxe/default");
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue