[syslinux:firmware] efi: only read ADV when booting from disk

syslinux-bot for Matt Fleming matt.fleming at intel.com
Wed Jul 3 04:27:06 PDT 2013


Commit-ID:  0aad5be4e47048a91ce007fdb630e407cb67c381
Gitweb:     http://www.syslinux.org/commit/0aad5be4e47048a91ce007fdb630e407cb67c381
Author:     Matt Fleming <matt.fleming at intel.com>
AuthorDate: Wed, 3 Jul 2013 11:45:02 +0100
Committer:  Matt Fleming <matt.fleming at intel.com>
CommitDate: Wed, 3 Jul 2013 12:14:35 +0100

efi: only read ADV when booting from disk

We aren't expecting to be able to access ldlinux.sys when booting over
PXE. Follow the pre-5.00 behaviour and simply initialise the ADV buffer
without even attempting to open the file. Also, delete all references to
EXTLINUX, we do not support it under EFI.

Without this patch we hang in efi_open() when booting PXELINUX because
no root volume is set as we're not booting from disk. This regression
was caused by commit a17fdfb8 ("com32: Catch up with GCC changes to
ctor/dtor funcs") because now constructors are actually being invoked on
EFI and efi_adv_init() is called by __syslinux_init().

Signed-off-by: Matt Fleming <matt.fleming at intel.com>

---
 efi/adv.c | 100 +++++++++++---------------------------------------------------
 efi/adv.h |   2 --
 2 files changed, 17 insertions(+), 85 deletions(-)

diff --git a/efi/adv.c b/efi/adv.c
index b390fd8..4056db1 100644
--- a/efi/adv.c
+++ b/efi/adv.c
@@ -24,11 +24,10 @@
  */
 #define  _GNU_SOURCE
 
+#include <syslinux/config.h>
 #include <string.h>
 #include "adv.h"
 
-#define IS_SYSLINUX	/* remove this: test build only */
-
 unsigned char syslinux_adv[2 * ADV_SIZE];
 
 static void cleanup_adv(unsigned char *advbuf)
@@ -183,93 +182,29 @@ int read_adv(const char *path, const char *cfg)
     return err;
 }
 
-/* For EFI platform, initialize ADV by opening ldlinux.sys or extlinux.sys
+/* For EFI platform, initialize ADV by opening ldlinux.sys
  * as configured and return the primary (adv0) and alternate (adv1)
  * data into caller's buffer. File remains open for subsequent
- * operations. This routine is to be called from comboot
- * vector. Currently only IS_SYSLINUX or IS_EXTLINUX is supported
- *
- * TODO:
- * 1. Need to set the path to ldlinux.sys or extlinux.sys; currently null
- * 2. What if there are errors?
+ * operations. This routine is to be called from comboot vector.
  */
 void efi_adv_init(void)
 {
-    char *name;
-    int rv;
-    int err = 0;
-    unsigned char *advbuf = syslinux_adv;
-    EFI_FILE_HANDLE	fd;	/* handle to ldlinux.sys or extlinux.sys */
-    CHAR16 *file;
-    EFI_FILE_INFO st, xst;
+    union syslinux_derivative_info sdi;
 
-#if defined IS_SYSLINUX
-    name = SYSLINUX_FILE;
-#elif defined IS_EXTLINUX
-    name = EXTLINUX_FILE;
-#else
-	#error "IS_SYSLINUX or IS_EXTLINUX must be specified to build ADV"
-#endif
-	/* FIXME: No path defined to syslinux/extlinux file */
-    rv = make_filespec(&file, "", name);
-    if (rv < 0 || !file) {
-	efi_errno = EFI_OUT_OF_RESOURCES;
-	efi_perror(L"efi_adv_init:");
-	return;
-    }
+    get_derivative_info(&sdi);
 
-    fd = efi_open(file, EFI_FILE_MODE_READ);
-    if (fd == (EFI_FILE_HANDLE)NULL) {
-	err = -1;
-	efi_printerr(L"efi_adv_init: Unable to open file %s\n", file);
-    } else if (efi_fstat(fd, &st)) {
-	err = -1;
-	efi_printerr(L"efi_adv_init: Unable to get info for file %s\n", file);
-    } else if (st.FileSize < 2 * ADV_SIZE) {
-	/* Too small to be useful */
-	err = -2;
-	efi_printerr(L"efi_adv_init: File %s size too small to be useful %s\n", file);
-    } else if (efi_xpread(fd, advbuf, 2 * ADV_SIZE,
-		      st.FileSize - 2 * ADV_SIZE) != 2 * ADV_SIZE) {
-	err = -1;
-	efi_printerr(L"efi_adv_init: Error reading ADV data from file %s\n", file);
-    } else {
-	/* We got it... maybe? */
+    if (sdi.c.filesystem == SYSLINUX_FS_SYSLINUX)
+	read_adv("", SYSLINUX_FILE);
+    else {
 	__syslinux_adv_ptr = &syslinux_adv[8]; /* skip head, csum */
 	__syslinux_adv_size = ADV_LEN;
 
-	err = syslinux_validate_adv(advbuf) ? -2 : 0;
-	if (!err) {
-	    /* Got a good one*/
-	    efi_clear_attributes(fd);
-
-	    /* Need to re-open read-write */
-	    efi_close(fd);
-		/* There is no SYNC attribute with EFI open */
-	    fd = efi_open(file, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE);
-		/* on error, only explicit comparison with null handle works */
-	    if (fd == (EFI_FILE_HANDLE)NULL) {
-		err = -1;
-		efi_perror(L"efi_adv_init:");
-	    } else if (efi_fstat(fd, &xst) || xst.FileSize != st.FileSize) {
-			/* device/inode info don't exist in the EFI file info structure */
-		efi_perror(L"efi_adv_init: file status error/mismatch");
-		err = -2;
-	    }
-		/* TODO: Do we need to set attributes of the sys file? */
-	}
-     }
-     if (file)
-	free(file);
-     if (fd != 0)
-	efi_close(fd);
-	/* TODO: In case of errors, we could set efi_errno to EFI_LOAD_ERROR
-	 * to mean that ADV could not be loaded up
-	 */
+	syslinux_validate_adv(syslinux_adv);
+    }
 }
 
 /* For EFI platform, write 2 * ADV_SIZE data to the file opened
- * at ADV initialization. (i.e ldlinux.sys or extlinux.sys).
+ * at ADV initialization. (i.e ldlinux.sys).
  *
  * TODO:
  * 1. Validate assumption: write back to file from __syslinux_adv_ptr
@@ -284,17 +219,16 @@ int efi_adv_write(void)
     unsigned char *advbuf = syslinux_adv;
     int rv;
     int err = 0;
-    EFI_FILE_HANDLE	fd;	/* handle to ldlinux.sys or extlinux.sys */
+    EFI_FILE_HANDLE	fd;	/* handle to ldlinux.sys */
     CHAR16 *file;
     EFI_FILE_INFO st, xst;
+    union syslinux_derivative_info sdi;
+
+    get_derivative_info(&sdi);
+    if (sdi.c.filesystem != SYSLINUX_FS_SYSLINUX)
+	return -1;
 
-#if defined IS_SYSLINUX
     name = SYSLINUX_FILE;
-#elif defined IS_EXTLINUX
-    name = EXTLINUX_FILE;
-#else
-	#error "IS_SYSLINUX or IS_EXTLINUX must be specified to build ADV"
-#endif
     rv = make_filespec(&file, "", name);
     if (rv < 0 || !file) {
 	efi_errno = EFI_OUT_OF_RESOURCES;
diff --git a/efi/adv.h b/efi/adv.h
index e8ccb35..419ad3b 100644
--- a/efi/adv.h
+++ b/efi/adv.h
@@ -8,9 +8,7 @@
 /* ADV information */
 #define ADV_SIZE	512	/* Total size */
 #define ADV_LEN		(ADV_SIZE-3*4)	/* Usable data size */
-/* Currently, one of IS_SYSLINUX or IS_EXTLINUX	must be defined for ADV */
 #define SYSLINUX_FILE	"ldlinux.sys"
-#define EXTLINUX_FILE	"extlinux.sys"
 
 #define ADV_MAGIC1	0x5a2d2fa5	/* Head signature */
 #define ADV_MAGIC2	0xa3041767	/* Total checksum */


More information about the Syslinux-commits mailing list