mirror of
https://github.com/xcat2/xcat-dep.git
synced 2024-11-24 02:19:53 +00:00
cdea944d09
Former-commit-id: 395b0dd95036aa3554d56720836c496a620d5dc0
330 lines
10 KiB
Diff
330 lines
10 KiB
Diff
diff -urN elilo/elilo.c elilo-xcat/elilo.c
|
|
--- elilo/elilo.c 2010-11-09 18:17:37.000000000 -0500
|
|
+++ elilo-xcat/elilo.c 2011-09-29 15:34:52.103299151 -0400
|
|
@@ -346,6 +346,7 @@
|
|
{
|
|
EFI_STATUS status;
|
|
EFI_PXE_BASE_CODE *pxe;
|
|
+ return;
|
|
|
|
#define FAKE_ELILONAME L"elilo-forced"
|
|
|
|
diff -urN elilo/fs/netfs.c elilo-xcat/fs/netfs.c
|
|
--- elilo/fs/netfs.c 2009-10-26 16:37:05.000000000 -0400
|
|
+++ elilo-xcat/fs/netfs.c 2011-09-29 15:34:52.107299010 -0400
|
|
@@ -66,6 +66,7 @@
|
|
|
|
typedef struct {
|
|
EFI_PXE_BASE_CODE *pxe;
|
|
+ IPXE_DOWNLOAD_PROTOCOL *ipxe;
|
|
EFI_HANDLE dev; /* handle to device we're attached to */
|
|
BOOLEAN using_pxe; /* true if downloaded using the PXE protocol vs. regular DHCP */
|
|
|
|
@@ -81,6 +82,13 @@
|
|
|
|
} netfs_priv_state_t;
|
|
|
|
+typedef struct {
|
|
+ BOOLEAN xfer_complete;
|
|
+ EFI_STATUS status;
|
|
+ IPXE_DOWNLOAD_FILE ipxefile;
|
|
+ netfs_fd_t *fbuf;
|
|
+} ipxe_context_t;
|
|
+
|
|
#define NETFS_F2FD(l,f) (UINTN)((f)-(l)->fd_tab)
|
|
#define NETFS_FD2F(l,fd) ((l)->fd_tab+fd)
|
|
#define NETFS_F_INVALID(f) ((f)->is_valid == FALSE)
|
|
@@ -106,6 +114,8 @@
|
|
|
|
static EFI_GUID NetFsProtocol = NETFS_PROTOCOL;
|
|
|
|
+EFI_GUID iPxeDlProtocol = IPXE_DOWNLOAD_PROTOCOL_GUID;
|
|
+
|
|
|
|
#if 0
|
|
static EFI_PXE_BASE_CODE_CALLBACK_STATUS
|
|
@@ -280,6 +290,46 @@
|
|
return pxe->Dhcp(pxe, FALSE);
|
|
}
|
|
|
|
+/* This function is called by iPXE to deliver a chunk of data for elilo to place in the correct place */
|
|
+static EFI_STATUS EFIAPI ipxe_datahandler(IN ipxe_context_t *context,IN CHAR8* buffer, IN UINTN len, IN UINTN offset) {
|
|
+ CHAR8 *newbuffer;
|
|
+ UINTN newmemamount;
|
|
+ if (len+offset > context->fbuf->netbuf_maxsize) { /* we have more data than we have room for */
|
|
+ if (len == 0) { /* iPXE will, if possible, send a '0' length buffer with offset to indicate total size.. */
|
|
+ newmemamount = offset;
|
|
+ } else {
|
|
+ /* it is also entirely possible iPXE could not deliver that heads up. Consequently, do what the tftp code did,
|
|
+ * except without having to restart the transfer on the network */
|
|
+ newmemamount = context->fbuf->netbuf_maxsize + NETFS_DEFAULT_BUFSIZE_INC;
|
|
+ }
|
|
+ /* Since we are potentially copying data over, it's less work to do the alloc directly than use the fdalloc convenience function */
|
|
+ newbuffer = (CHAR8 *)alloc_pages(EFI_SIZE_TO_PAGES(newmemamount), EfiLoaderData, AllocateAnyPages, 0);
|
|
+ if (newbuffer && context->fbuf->netbuf && context->fbuf->netbuf_size > 0) { /* there is data to copy over into the new memory space
|
|
+ * do so since it's much cheaper than redownloading */
|
|
+ Memcpy(newbuffer, context->fbuf->netbuf, context->fbuf->netbuf_size);
|
|
+ }
|
|
+ free(context->fbuf->netbuf); //Done with the old memory, can free and move the pointer
|
|
+ context->fbuf->netbuf=newbuffer;
|
|
+ context->fbuf->netbuf_maxsize = newmemamount; //rememeber that the buffer is larger now
|
|
+ }
|
|
+ if (len && (len+offset > context->fbuf->netbuf_size)) {
|
|
+ /* if len is zero, then offset is total size of the file, not size used so far,
|
|
+ * therefore only update the size when len is non-zero.
|
|
+ * if data comes in out of order, previous undefined data counts towards the size,
|
|
+ * but that's no big deal since the only ill-effect is that memcpy copies more memory than it needs to if the buffer exhausts */
|
|
+ context->fbuf->netbuf_size = len+offset;
|
|
+ }
|
|
+ if (len == 0) { return EFI_SUCCESS; } /* TODO: could use this to power a progress indicator/percentage, for now do no more than Mtftp */
|
|
+ Memcpy(context->fbuf->netbuf+offset,buffer,len);
|
|
+ return EFI_SUCCESS;
|
|
+}
|
|
+
|
|
+/* This function is called by iPXE when the transfer either completes successfully or errors out and cannot succeed */
|
|
+EFI_STATUS EFIAPI ipxe_finished (ipxe_context_t *context,EFI_STATUS status) {
|
|
+ context->xfer_complete = TRUE; /* for better or for worse, we are done with this file */
|
|
+ context->status = status; /* iPXE makes no effort to translate it's errors to UEFI errors, but the high bit is set if appropriate */
|
|
+ return EFI_SUCCESS; /* we are returning this to iPXE, so we are successful in accepting the status, not indicating the transfer is successful */
|
|
+}
|
|
static EFI_STATUS
|
|
netfs_open(netfs_interface_t *this, CHAR16 *name, UINTN *fd)
|
|
{
|
|
@@ -338,7 +388,24 @@
|
|
return status;
|
|
}
|
|
|
|
-/*
|
|
+ if (nfs->ipxe) {
|
|
+ ipxe_context_t context;
|
|
+ context.xfer_complete=FALSE;
|
|
+ context.fbuf=f;
|
|
+ status = uefi_call_wrapper(nfs->ipxe->Start,6,
|
|
+ nfs->ipxe,
|
|
+ ascii_name,
|
|
+ &ipxe_datahandler,
|
|
+ &ipxe_finished,
|
|
+ &context,
|
|
+ &context.ipxefile);
|
|
+ while (context.xfer_complete == FALSE) {
|
|
+ uefi_call_wrapper(nfs->ipxe->Poll,1,
|
|
+ nfs->ipxe);
|
|
+ }
|
|
+ status = context.status;
|
|
+ } else {
|
|
+ /*
|
|
* netboot bugfix SF tracker 2874380
|
|
* EFI 1.10 spec
|
|
* For read operations, the return data will be placed in the buffer specified by BufferPtr. If
|
|
@@ -449,12 +516,12 @@
|
|
retries++;
|
|
goto retry;
|
|
}
|
|
-
|
|
} else if (status == EFI_TIMEOUT) { //if just a simple timeout, buffers are good just retry
|
|
VERB_PRT(2, Print(L"TFTP returned EFI_TIMEOUT ERROR... %d retries left.\n", (2 - retries)));
|
|
retries++;
|
|
goto retry;
|
|
}
|
|
+ }
|
|
if (status == EFI_SUCCESS) {
|
|
/* start at the beginning of the file */
|
|
f->netbuf_pos = 0;
|
|
@@ -706,7 +773,7 @@
|
|
}
|
|
|
|
static VOID
|
|
-netfs_init_state(netfs_t *netfs, EFI_HANDLE dev, EFI_PXE_BASE_CODE *pxe)
|
|
+netfs_init_state(netfs_t *netfs, EFI_HANDLE dev, EFI_PXE_BASE_CODE *pxe, IPXE_DOWNLOAD_PROTOCOL *ipxe)
|
|
{
|
|
netfs_priv_state_t *nfs = FS_PRIVATE(netfs);
|
|
UINTN i;
|
|
@@ -726,6 +793,7 @@
|
|
|
|
nfs->dev = dev;
|
|
nfs->pxe = pxe;
|
|
+ nfs->ipxe = ipxe;
|
|
|
|
/*
|
|
* we defer DHCP request until it is really necessary (netfs_open)
|
|
@@ -750,6 +818,7 @@
|
|
EFI_STATUS status;
|
|
netfs_t *netfs;
|
|
EFI_PXE_BASE_CODE *pxe;
|
|
+ IPXE_DOWNLOAD_PROTOCOL *ipxe;
|
|
|
|
status = uefi_call_wrapper(BS->HandleProtocol, 3, dev, &NetFsProtocol, (VOID **)&netfs);
|
|
if (status == EFI_SUCCESS) {
|
|
@@ -760,6 +829,9 @@
|
|
status = uefi_call_wrapper(BS->HandleProtocol, 3, dev, &PxeBaseCodeProtocol, (VOID **)&pxe);
|
|
if (EFI_ERROR(status)) return EFI_INVALID_PARAMETER;
|
|
|
|
+ status = uefi_call_wrapper(BS->HandleProtocol, 3, dev, &iPxeDlProtocol, (VOID **)&ipxe);
|
|
+ if (EFI_ERROR(status)) ipxe=NULL;
|
|
+
|
|
|
|
netfs = (netfs_t *)alloc(sizeof(*netfs), EfiLoaderData);
|
|
if (netfs == NULL) {
|
|
@@ -767,7 +839,7 @@
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
- netfs_init_state(netfs, dev, pxe);
|
|
+ netfs_init_state(netfs, dev, pxe, ipxe);
|
|
|
|
status = LibInstallProtocolInterfaces(&dev, &NetFsProtocol, netfs, NULL);
|
|
if (EFI_ERROR(status)) {
|
|
diff -urN elilo/fs/netfs.h elilo-xcat/fs/netfs.h
|
|
--- elilo/fs/netfs.h 2003-08-19 12:45:01.000000000 -0400
|
|
+++ elilo-xcat/fs/netfs.h 2011-09-29 15:34:52.109299525 -0400
|
|
@@ -31,6 +31,74 @@
|
|
|
|
#define NETFS_BOOTFILE_MAXLEN 256
|
|
|
|
+#define IPXE_DOWNLOAD_PROTOCOL_GUID { 0x3eaeaebd, 0xdecf, 0x493b, { 0x9b, 0xd1, 0xcd, 0xb2, 0xde, 0xca, 0xe7, 0x19 } }
|
|
+typedef VOID *IPXE_DOWNLOAD_FILE;
|
|
+
|
|
+/**
|
|
+ * iPXE download protocol interface
|
|
+ * This will be attached to the DeviceHandle that elilo booted from if iPXE chained it.
|
|
+ */
|
|
+#ifdef __GNUC__
|
|
+#if __x86_64__
|
|
+#define EFIAPI __attribute__((ms_abi))
|
|
+#elif __i386__
|
|
+#define EFIAPI __attribute__((cdecl,regparm(0)))
|
|
+#endif
|
|
+#endif
|
|
+
|
|
+typedef struct _IPXE_DOWNLOAD_PROTOCOL IPXE_DOWNLOAD_PROTOCOL;
|
|
+typedef
|
|
+EFI_STATUS
|
|
+(EFIAPI *IPXE_DOWNLOAD_DATA_CALLBACK)(
|
|
+ IN VOID *Context,
|
|
+ IN VOID *Buffer,
|
|
+ IN UINTN BufferLength,
|
|
+ IN UINTN FileOffset
|
|
+ );
|
|
+typedef
|
|
+void
|
|
+(EFIAPI *IPXE_DOWNLOAD_FINISH_CALLBACK)(
|
|
+ IN VOID *Context,
|
|
+ IN EFI_STATUS Status
|
|
+ );
|
|
+typedef
|
|
+EFI_STATUS
|
|
+(EFIAPI *IPXE_DOWNLOAD_ABORT)(
|
|
+ IN IPXE_DOWNLOAD_PROTOCOL *This,
|
|
+ IN IPXE_DOWNLOAD_FILE File,
|
|
+ IN EFI_STATUS Status
|
|
+ );
|
|
+
|
|
+
|
|
+typedef
|
|
+EFI_STATUS
|
|
+(EFIAPI *IPXE_DOWNLOAD_START)(
|
|
+ IN IPXE_DOWNLOAD_PROTOCOL *This,
|
|
+ IN CHAR8 *Url,
|
|
+ IN IPXE_DOWNLOAD_DATA_CALLBACK DataCallback,
|
|
+ IN IPXE_DOWNLOAD_FINISH_CALLBACK FinishCallback,
|
|
+ IN VOID *Context,
|
|
+ OUT IPXE_DOWNLOAD_FILE *File
|
|
+ );
|
|
+typedef
|
|
+EFI_STATUS
|
|
+(EFIAPI *IPXE_DOWNLOAD_POLL)(
|
|
+ IN IPXE_DOWNLOAD_PROTOCOL *This
|
|
+ );
|
|
+
|
|
+
|
|
+
|
|
+struct _IPXE_DOWNLOAD_PROTOCOL {
|
|
+ IPXE_DOWNLOAD_START Start;
|
|
+ IPXE_DOWNLOAD_ABORT Abort;
|
|
+ IPXE_DOWNLOAD_POLL Poll;
|
|
+};
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+
|
|
typedef struct {
|
|
EFI_IP_ADDRESS cln_ipaddr;
|
|
EFI_IP_ADDRESS srv_ipaddr;
|
|
diff -urN elilo/glue_netfs.c elilo-xcat/glue_netfs.c
|
|
--- elilo/glue_netfs.c 2010-11-09 18:18:41.000000000 -0500
|
|
+++ elilo-xcat/glue_netfs.c 2011-09-29 15:35:10.743298070 -0400
|
|
@@ -63,6 +63,7 @@
|
|
#define NETFS_KERNEL_LAYER 2
|
|
|
|
static CHAR16 *hexa=L"0123456789ABCDEF";
|
|
+static CHAR16 *hexal=L"0123456789abcdef";
|
|
|
|
static VOID
|
|
convert_mac2hex(UINT8 *hw_addr,INTN l, CHAR16 *str)
|
|
@@ -78,6 +79,19 @@
|
|
}
|
|
|
|
static VOID
|
|
+convert_mac2hexhyp(UINT8 *hw_addr,INTN l, CHAR16 *str)
|
|
+{
|
|
+ UINTN i;
|
|
+
|
|
+ for (i=0 ; i < l; i++) {
|
|
+ str[3*i] = hexal[(hw_addr[i] & 0xf0)>>4];
|
|
+ str[3*i+1] = hexal[hw_addr[i] & 0x0f];
|
|
+ str[3*i+2] = '-';
|
|
+ }
|
|
+ str[3*l-1]='\0';
|
|
+}
|
|
+
|
|
+static VOID
|
|
convert_ip2hex(UINT8 *ip, INTN l, CHAR16 *str)
|
|
{
|
|
UINTN i;
|
|
@@ -162,8 +176,15 @@
|
|
convert_ip2decstr(ip, m, str);
|
|
set_var(VAR_NETFS_GATEWAY, str);
|
|
|
|
+ ip = info.using_ipv6 ? info.srv_ipaddr.v6.Addr: info.srv_ipaddr.v4.Addr;
|
|
+ convert_ip2decstr(ip, m, str);
|
|
+ set_var(VAR_NETFS_NEXTSERVER, str);
|
|
+
|
|
set_var(VAR_NETFS_HOSTNAME, info.hostname);
|
|
set_var(VAR_NETFS_DOMAINAME, info.domainame);
|
|
+ StrCpy(str, L"01-");
|
|
+ convert_mac2hexhyp(info.hw_addr,6,str+3);
|
|
+ set_var(VAR_NETFS_BOOTIF, str);
|
|
|
|
if (info.using_pxe) {
|
|
DBG_PRT((L"netfs_setdefaults: using_pxe"));
|
|
diff -urN elilo/Make.defaults elilo-xcat/Make.defaults
|
|
--- elilo/Make.defaults 2011-01-10 16:05:30.000000000 -0500
|
|
+++ elilo-xcat/Make.defaults 2011-09-29 15:34:52.119298670 -0400
|
|
@@ -55,9 +55,9 @@
|
|
# They are installed as part of the GNU-EFI package installation
|
|
#
|
|
EFIINC = /usr/include/efi
|
|
-GNUEFILIB = /usr/lib
|
|
-EFILIB = /usr/lib
|
|
-EFICRT0 = /usr/lib
|
|
+GNUEFILIB = /usr/lib64
|
|
+EFILIB = /usr/lib64/gnuefi
|
|
+EFICRT0 = /usr/lib64/gnuefi
|
|
|
|
CDIR := $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi)
|
|
TOPDIR =
|
|
diff -urN elilo/vars.h elilo-xcat/vars.h
|
|
--- elilo/vars.h 2003-08-19 12:48:14.000000000 -0400
|
|
+++ elilo-xcat/vars.h 2011-09-29 15:35:02.359299180 -0400
|
|
@@ -45,6 +45,8 @@
|
|
#define VAR_NETFS_GATEWAY L'G' /* the gateway obtained by DHCP/PXE */
|
|
#define VAR_NETFS_HOSTNAME L'H' /* the hostname obtained by DHCP/PXE */
|
|
#define VAR_NETFS_DOMAINAME L'D' /* the domain name obtained by DHCP/PXE */
|
|
+#define VAR_NETFS_BOOTIF L'B' /* the hardware address used for DHCP/PXE */
|
|
+#define VAR_NETFS_NEXTSERVER L'N' /* the next server from DHCP/PXE */
|
|
|
|
extern INTN set_var(CHAR16 v, CHAR16 *value);
|
|
extern CHAR16 * get_var(CHAR16 v);
|