[syslinux] [PATCH 0/1] EFI access from Com32 modules

Patrick Masotta
Sat, 14 Mar 2015 11:23:26 -0000

This patch adds to Com32 modules the capabilities of accessing the EFI
environment

The idea is simple, the EFI parameters "image" and "table"
received by syslinux.efi's
efi_main()  are stored in the "firmware" structure, next they are
retrieved from the Com32
module which is linked against the gnu-efi static library. The Com32 module can
use the EFI
environment after calling InitializeLib(image, systab);
With this patch coding i.e. pxechn.c32 able to run on EFI environments should be
a trivial job.

It was tested on VMware BIOS/EFI clients and HP Elitebook EFI/BIOS notebooks,

Feedback appreciated.

Best,
Patrick

 Signed-off-by: Patrick Masotta <masottaus at yahoo.com>
 ---

diff -uprN a/com32/include/syslinux/firmware.h
b/com32/include/syslinux/firmware.h
--- a/com32/include/syslinux/firmware.h	2014-10-06 10:27:44.000000000 -0600
+++ b/com32/include/syslinux/firmware.h	2015-03-13 12:59:12.147356419 -0600
@@ -62,6 +62,8 @@ struct firmware {
 			  struct setup_data *, char *);
 	struct vesa_ops *vesa;
 	struct mem_ops *mem;
+	void* image;
+	void** table;
 };

 extern struct firmware *firmware;
diff -uprN a/com32/modules/elf_bios_efi.c b/com32/modules/elf_bios_efi.c
--- a/com32/modules/elf_bios_efi.c	1969-12-31 17:00:00.000000000 -0700
+++ b/com32/modules/elf_bios_efi.c	2015-03-13 14:43:18.266718706 -0600
@@ -0,0 +1,116 @@
+/*
+ * Demo module showing EFI access from a com32 module
+ * 		by Patrick Masotta (Serva) (c) 2015
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <consoles.h>
+#include <console.h>
+#include <errno.h>
+#include <string.h>
+#include <syslinux/config.h>
+#include <syslinux/loadfile.h>
+#include <syslinux/bootrm.h>
+#include <syslinux/video.h>
+#include <com32.h>
+#include <stdint.h>
+#include <syslinux/pxe.h>
+#include <sys/gpxe.h>
+#include <unistd.h>
+#include <getkey.h>
+#include <dhcp.h>
+#include <limits.h>
+
+#ifndef __FIRMWARE_BIOS__
+
+#include <syslinux/firmware.h>
+#include "../../efi/efi.h"
+
+#endif
+
+
+
+#ifdef __FIRMWARE_BIOS__
+
+int pressanykey(void) {
+    int inc;
+
+    printf("Press any key to continue. ");
+    inc = KEY_NONE;
+    while (inc == KEY_NONE)
+	inc = get_key(stdin, 6000);
+    puts("");
+    return inc;
+}
+
+int doTheJob(void)
+{
+
+	 printf("This Com32 instance of elf_bios_efi.c32 is running on a BIOS
environment\n");
+			pressanykey();
+
+	return 0;
+}
+
+#else
+
+char efi_getchar(char *hi)
+{
+	SIMPLE_INPUT_INTERFACE *in = ST->ConIn;
+	EFI_INPUT_KEY key;
+	EFI_STATUS status;
+
+
+	status = WaitForSingleEvent(in->WaitForKey, 0); 			// 0=> no timeout
+	status = uefi_call_wrapper(in->ReadKeyStroke, 2, in, &key);	// get the
char
+
+	if (!key.ScanCode)
+		return (char)key.UnicodeChar;
+
+	/*
+	 * We currently only handle scan codes that fit in 8 bits.
+	 */
+	 if(hi)
+		*hi = (char)key.ScanCode;
+
+	return 0;
+
+}
+
+EFI_HANDLE 			image	= NULL;
+EFI_SYSTEM_TABLE* 	systab	= NULL;
+
+int doTheJob(void)
+{
+
+
+	image 	= (EFI_HANDLE) firmware->image;
+	systab	= (EFI_SYSTEM_TABLE*) firmware->table;
+
+	InitializeLib(image, systab);
+
+	//Clear screen
+	uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
+
+	Print(L"This Com32 instance of elf_bios_efi.c32 is running on an EFI
environment\nPress any key to continue...");
+	efi_getchar(NULL);
+
+	return 0;
+}
+
+
+#endif
+
+
+
+
+int main(int argc, char *argv[])
+{
+
+
+	return doTheJob();
+
+
+}
diff -uprN a/com32/modules/Makefile b/com32/modules/Makefile
--- a/com32/modules/Makefile	2014-10-06 10:27:44.000000000 -0600
+++ b/com32/modules/Makefile	2015-03-13 13:37:44.416274394 -0600
@@ -18,13 +18,17 @@
 VPATH = $(SRC)
 include $(MAKEDIR)/elf.mk

+ifneq "$(FIRMWARE)" "BIOS"
+include $(MAKEDIR)/elf_efi.mk
+endif
+
 MODULES	  = config.c32 ethersel.c32 dmitest.c32 cpuidtest.c32 \
 	    disk.c32 pcitest.c32 elf.c32 linux.c32 reboot.c32 pmload.c32 \
 	    meminfo.c32 sdi.c32 sanboot.c32 ifcpu64.c32 vesainfo.c32 \
 	    kbdmap.c32 cmd.c32 vpdtest.c32 host.c32 ls.c32 gpxecmd.c32 \
 	    ifcpu.c32 cpuid.c32 cat.c32 pwd.c32 ifplop.c32 zzjson.c32 \
 	    whichsys.c32 prdhcp.c32 pxechn.c32 kontron_wdt.c32 ifmemdsk.c32 \
-	    hexdump.c32 poweroff.c32 cptime.c32 debug.c32
+	    hexdump.c32 poweroff.c32 cptime.c32 debug.c32 elf_bios_efi.c32

 TESTFILES
diff -uprN a/efi/build-gnu-efi.sh b/efi/build-gnu-efi.sh
--- a/efi/build-gnu-efi.sh	2014-10-06 10:27:44.000000000 -0600
+++ b/efi/build-gnu-efi.sh	2015-03-13 13:07:51.577939127 -0600
@@ -21,23 +21,23 @@ fi
 ARCH="$1"
 objdir="$(readlink -f $2)"

-if [ ! -e ../version.h ]; then
-    printf "build-gnu-efi.sh: Cannot be run outside Syslinux object
tree\n"
-    pwd
-    exit 1
-fi
-
-(
-	cd ../..
-	git submodule update --init
-)
+#if [ ! -e ../version.h ]; then
+#    printf "build-gnu-efi.sh: Cannot be run outside Syslinux object
tree\n"
+#    pwd
+#    exit 1
+#fi
+#
+#(
+#	cd ../..
+#	git submodule update --init
+#)

 mkdir -p "$objdir/gnu-efi"
 cd "$objdir/gnu-efi"

-EFIDIR="$(readlink -f "$objdir/../gnu-efi/gnu-efi-3.0")"
+EFIDIR="$(readlink -f "$topdir/gnu-efi/gnu-efi-3.0")"

 make SRCDIR="$EFIDIR" TOPDIR="$EFIDIR" -f
"$EFIDIR/Makefile" ARCH=$ARCH
 make SRCDIR="$EFIDIR" TOPDIR="$EFIDIR" -f
"$EFIDIR/Makefile" ARCH=$ARCH PREFIX="$objdir" install

-cd "$objdir/efi"
+cd "$objdir"
diff -uprN a/efi/check-gnu-efi.sh b/efi/check-gnu-efi.sh
--- a/efi/check-gnu-efi.sh	2014-10-06 10:27:44.000000000 -0600
+++ b/efi/check-gnu-efi.sh	2015-03-13 13:11:01.575274084 -0600
@@ -25,7 +25,8 @@ if [ ! \( -f "$objdir/include/efi/$ARCH/
     # Syslinux disables built-in implicit rules.
     export MAKEFLAGS
-    ../../efi/build-gnu-efi.sh $ARCH "$objdir" > /dev/null
2>&1
+    $topdir/efi/build-gnu-efi.sh $ARCH "$objdir"
+
     if [ $? -ne 0 ]; then
 	printf "Failed to build gnu-efi. "
 	printf "Execute the following command for full details: \n\n"
diff -uprN a/efi/clean-gnu-efi.sh b/efi/clean-gnu-efi.sh
--- a/efi/clean-gnu-efi.sh	2014-10-06 10:27:44.000000000 -0600
+++ b/efi/clean-gnu-efi.sh	2015-03-13 13:11:33.200161911 -0600
@@ -21,10 +21,10 @@ fi
 ARCH="$1"
 objdir=$(readlink -f "$2")

-(
-	cd ../..
-	git submodule update --init
-)
+#(
+#	cd ../..
+#	git submodule update --init
+#)

 if [ -d "$objdir/gnu-efi" ];then
 	cd "$objdir/gnu-efi"
diff -uprN a/efi/main.c b/efi/main.c
--- a/efi/main.c	2014-10-06 10:27:44.000000000 -0600
+++ b/efi/main.c	2015-03-13 12:56:38.747049818 -0600
@@ -1202,6 +1202,8 @@ struct firmware efi_fw = {
 	.boot_linux = efi_boot_linux,
 	.vesa = &efi_vesa_ops,
 	.mem = &efi_mem_ops,
+	.image = NULL,
+	.table = NULL
 };

 static inline void syslinux_register_efi(void)
@@ -1265,6 +1267,8 @@ EFI_STATUS efi_main(EFI_HANDLE image, EF
 	InitializeLib(image, table);

 	image_handle = image;
+	efi_fw.image = (void*) image;
+	efi_fw.table = (void**) table;
 	syslinux_register_efi();

 	efi_console_save();
diff -uprN a/mk/elf_efi.mk b/mk/elf_efi.mk
--- a/mk/elf_efi.mk	1969-12-31 17:00:00.000000000 -0700
+++ b/mk/elf_efi.mk	2015-03-13 13:03:27.630529153 -0600
@@ -0,0 +1,76 @@
+#/*
+# * EFI access from a com32 module by Patrick Masotta (Serva) (c) 2015
+# */
+
+
+com32 = $(topdir)/com32
+core = $(topdir)/core
+
+# Support IA32 and x86_64 platforms with one build
+# Set up architecture specifics; for cross compilation, set ARCH as apt
+# gnuefi sets up architecture specifics in ia32 or x86_64 sub directories
+# set up the LIBDIR and EFIINC for building for the appropriate architecture
+
+GCCOPT := $(call gcc_ok,-fno-stack-protector,)
+
+EFIINC = $(objdir)/include/efi
+LIBDIR  = $(objdir)/lib
+
+ifeq ($(ARCH),i386)
+	ARCHOPT = -m32 -march=i386
+	EFI_SUBARCH = ia32
+endif
+ifeq ($(ARCH),x86_64)
+	ARCHOPT = -m64 -march=x86-64
+	EFI_SUBARCH = $(ARCH)
+endif
+
+
+
+CFLAGS  := $(CFLAGS)
+CFLAGS  += 	-I$(EFIINC) -I$(EFIINC)/$(EFI_SUBARCH) \
+			-DEFI_FUNCTION_WRAPPER -fPIC -fshort-wchar -ffreestanding \
+			-Wall \
+			-I$(core)/ $(ARCHOPT) \
+			-I$(com32)/lib/ -I$(com32)/libutil/include -std=gnu99 \
+			-DELF_DEBUG -DSYSLINUX_EFI -I$(objdir) \
+			$(GCCWARN) -D__COM32__ -D__FIRMWARE_$(FIRMWARE)__ -mno-red-zone \
+			-Wno-unused-parameter $(GCCOPT)
+
+
+
+
+## granular test pat
+LDFLAGS += -Bsymbolic -pie -nostdlib -znocombreloc \
+		-L$(LIBDIR) -m elf_$(ARCH) -E
+#
+#
+SFLAGS  += $(GCCOPT) $(GCCWARN) $(ARCHOPT) \
+	     -fomit-frame-pointer -D__COM32__ -D__FIRMWARE_$(FIRMWARE)__ \
+	     -nostdinc -iwithprefix include \
+	     -I$(com32)/libutil/include -I$(com32)/include -I$(com32)/include/sys
$(GPLINCLUDE)
+
+
+
+
+LIBEFI = $(objdir)/lib/libefi.a
+
+$(LIBEFI):
+	@echo Building gnu-efi for $(EFI_SUBARCH)
+	$(topdir)/efi/check-gnu-efi.sh $(EFI_SUBARCH) $(objdir)
+
+
+
+%.o: %.S	# Cancel old rule
+
+%.o: %.c
+
+.PRECIOUS: %.o
+%.o: %.S $(LIBEFI)
+	$(CC) $(SFLAGS) -c -o $@ $<
+
+.PRECIOUS: %.o
+%.o: %.c $(LIBEFI)
+	$(CC) $(CFLAGS) -c -o $@ $<
+
+