From f21803fa93d7649615d8281417adea154b017451 Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Sun, 30 Jul 2017 23:20:11 +0100 Subject: [PATCH] enable, fix and document EDK2 Linux compilation * Still to be considered EXPERIMENTAL at this stage --- .gitattributes | 1 + EfiFsPkg/Affs.inf | 1 + README.md | 83 +++++++++++++++++++++++++++++++++++------------ set_grub_cpu.cmd | 22 +++++++------ set_grub_cpu.sh | 13 ++++++++ src/driver.h | 7 ++++ src/file.c | 26 +++++++-------- src/logging.c | 2 +- src/missing.c | 2 +- 9 files changed, 112 insertions(+), 45 deletions(-) create mode 100755 set_grub_cpu.sh diff --git a/.gitattributes b/.gitattributes index 940f918..40e170a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,6 +2,7 @@ * text=auto # git apply may fail unless it is fed LF terminated patches... *.patch eol=lf +*.sh eol=lf *.c text *.h text *.md text diff --git a/EfiFsPkg/Affs.inf b/EfiFsPkg/Affs.inf index af787ab..4e0df1e 100644 --- a/EfiFsPkg/Affs.inf +++ b/EfiFsPkg/Affs.inf @@ -71,3 +71,4 @@ *_*_*_CC_FLAGS = -Os -DCPU_$(ARCH) -DGRUB_FILE=__FILE__ -DDRIVERNAME=$(BASE_NAME) -DDRIVERNAME_STR="\"Amiga FFS\"" # On MSFT compilers, we must force-disable the default /GL option in order to replace the memset() intrinsic MSFT:*_*_*_CC_FLAGS = /GL- /wd4028 /wd4068 /wd4133 /wd4146 /wd4201 /wd4204 /wd4244 /wd4245 /wd4267 /wd4311 /wd4312 /wd4334 /wd4706 + GCC:*_*_*_CC_FLAGS = -Wno-overflow diff --git a/README.md b/README.md index 6de7b5f..1aa9234 100644 --- a/README.md +++ b/README.md @@ -9,37 +9,51 @@ For additional info as well as precompiled drivers, see http://efi.akeo.ie ## Requirements * [Visual Studio 2017](https://www.visualstudio.com/vs/community/) (Windows), MinGW (Windows), gcc (Linux) or - [EDK2](https://github.com/tianocore/edk2)/VS2015 (Windows). Note that EDK2 is supported with the Visual - Studio compiler __only__. + [EDK2](https://github.com/tianocore/edk2). * A git client able to initialize/update submodules * [QEMU](http://www.qemu.org) __v2.7 or later__ if debugging with Visual Studio (NB: You can find QEMU Windows binaries [here](https://qemu.weilnetz.de/w64/)) ## Compilation -* [_Common_] Fetch the git submodules with `git submodule init` and `git submodule update`. -* [_Common_] Apply the included f2fs patch to the `grub\` subdirectory. This adds F2FS support, - which is not yet included in GRUB2. -* [_Visual Studio_] Apply the other patches to the `grub\` subdirectory. If you are using Clang/C2 - you can apply the first patch only. If you are using MSVC, you must apply 2 patches and if you - are using EDK2 you should apply all of them. -* [_Visual Studio_] Open the solution file and hit `F5` to compile and debug the default driver. -* [_EDK2_] Open and elevated command prompt and create a symbolic link, inside your - EDK2 directory, to the EfiFs source. For instance, if you have EKD2 in `C:\edk2` and EfiFs in `C:\efifs`, - youd should run `mklink /D EfiFsPkg C:\efifs` inside the `C:\edk2` directory. -* [_EDK2_] Open a Visual Studio command prompt and, after having invoked `Edk2Setup.bat` run something like: +### Common + +* Fetch the git submodules with `git submodule init` and `git submodule update`. +* Apply the included f2fs patch to the `grub\` subdirectory. This adds F2FS support, which is not + yet included in GRUB2. +* Apply the other patches to the `grub\` subdirectory. + +### Visual Studio (non EDK2) + +* Open the solution file and hit `F5` to compile and debug the default driver. + +### gcc (non EDK2) + +* Run `make` in the top directory. If needed you can also issue something like + `make ARCH= CROSS_COMPILE=` where `` is one of `ia32`, `x64`, `arm` or + `aa64` (the __official__ UEFI abbreviations for an arch, as used in `/efi/boot/boot[ARCH].efi`) + and tuple is the one for your cross-compiler, such as `arm-linux-gnueabihf-`. + e.g. `make ARCH=aa64 CROSS_COMPILE=aarch64-linux-gnu-` + +### EDK2 + +* Open an elevated command prompt and create a symbolic link called `EfiFsPkg`, inside your EDK2 + directory, to the EfiFs source. On Windows, from an elevated prompt, you could run something like + `mklink /D EfiFsPkg C:\efifs`, and on Linux `ln -s ../efifs EfiFsPkg`. +* From a command prompt, set Grub to target the platform you are compiling for by invoking: + * (Windows) `set_grub_cpu.cmd ` + * (Linux) `./set_grub_cpu.sh ` + Where `` is one of `ia32`, `x64`, `arm` or `aa64`. + Note that you __MUST__ invoke the `set_grub_cpu` script __every time you switch target__. +* After having invoked `Edk2Setup.bat` (Windows) or `edksetup.sh` (Linux) run something like: ``` - build -a X64 -b RELEASE -t VS2015 -p EfiFsPkg/EfiFsPkg.dsc + build -a X64 -b RELEASE -t -p EfiFsPkg/EfiFsPkg.dsc ``` + where `` is something like `VS2015` (Windows) or `GCC5` (Linux). NB: To build an individual driver, such as NTFS, you would can also use something like: ``` - build -a X64 -b RELEASE -t VS2015 -p EfiFsPkg/EfiFsPkg.dsc -m EfiFsPkg/EfiFsPkg/Ntfs.inf + build -a X64 -b RELEASE -t -p EfiFsPkg/EfiFsPkg.dsc -m EfiFsPkg/EfiFsPkg/Ntfs.inf ``` -* [_gcc_] Run `make` in the top directory. If needed you can also issue something like - `make ARCH= CROSS_COMPILE=` where `` is one of `ia32`, `x64`, `arm` or - `aa64` (the __official__ UEFI abbreviations for an arch, as used in `/efi/boot/boot[ARCH].efi`) - and tuple is the one for your cross-compiler, such as `arm-linux-gnueabihf-`. - e.g. `make ARCH=aa64 CROSS_COMPILE=aarch64-linux-gnu-` ## Testing @@ -76,3 +90,32 @@ While in this section, you may also want to select the installation of _Clang/C2 This is a pure GPLv3+ implementation of EFI drivers. Great care was taken not to use non GPLv3 compatible sources, such as rEFInd's `fsw_efi` (GPLv2 only) or Intel's FAT driver (requires an extra copyright notice). + +## Bonus: Commands to compile EfiFs using EDK2 on Debian GNU/Linux 9.1 + +As root: +``` +apt-get install nasm uuid-dev gcc-arm-linux-gnueabihf gcc-aarch64-linux-gnu +cd /usr/src +git clone https://github.com/tianocore/edk2.git +git clone https://github.com/pbatard/efifs.git +cd efifs +git submodule init +git submodule update +cd grub +git am ../*.patch +cd /usr/src/edk2 +ln -s ../efifs EfiFsPkg +make -C /usr/src/edk2/BaseTools/Source/C +export GCC5_ARM_PREFIX=arm-linux-gnueabihf- +export GCC5_AARCH64_PREFIX=aarch64-linux-gnu- +source edksetup.sh +./EfiFsPkg/set_grub_cpu.sh X64 +build -a X64 -b RELEASE -t GCC5 -p EfiFsPkg/EfiFsPkg.dsc +./EfiFsPkg/set_grub_cpu.sh IA32 +build -a IA32 -b RELEASE -t GCC5 -p EfiFsPkg/EfiFsPkg.dsc +./EfiFsPkg/set_grub_cpu.sh ARM +build -a ARM -b RELEASE -t GCC5 -p EfiFsPkg/EfiFsPkg.dsc +./EfiFsPkg/set_grub_cpu.sh AARCH64 +build -a AARCH64 -b RELEASE -t GCC5 -p EfiFsPkg/EfiFsPkg.dsc +``` diff --git a/set_grub_cpu.cmd b/set_grub_cpu.cmd index 7021416..b1fc5fc 100644 --- a/set_grub_cpu.cmd +++ b/set_grub_cpu.cmd @@ -1,19 +1,21 @@ @echo off set ARCH= -if "%1"=="Win32" set ARCH=i386 -if "%1"=="x64" set ARCH=x86_64 -if "%1"=="ARM" set ARCH=arm -if "%1"=="ARM64" set ARCH=arm64 +if /I "%1"=="win32" set ARCH=i386 +if /I "%1"=="ia32" set ARCH=i386 +if /I "%1"=="x64" set ARCH=x86_64 +if /I "%1"=="arm" set ARCH=arm +if /I "%1"=="arm64" set ARCH=arm64 +if /I "%1"=="aa64" set ARCH=arm64 if "%ARCH%"=="" ( echo Unsupported arch %1 exit 1 ) -echo %ARCH% +echo Setting GRUB for %ARCH%... -if not exist "cpu\%ARCH%" ( - echo Duplicating GRUB include\grub\%ARCH%\ to include\grub\cpu\ - rmdir /S /Q cpu >NUL 2>&1 - xcopy "%ARCH%" "cpu" /i /q /s /y /z - echo %ARCH% > cpu/%ARCH% +if not exist "%~dp0\grub\include\grub\cpu\%ARCH%" ( + echo Duplicating grub\include\grub\%ARCH%\ to grub\include\grub\cpu\ + rmdir /S /Q "%~dp0\grub\include\grub\cpu" >NUL 2>&1 + xcopy "%~dp0\grub\include\grub\%ARCH%" "%~dp0\grub\include\grub\cpu" /i /q /s /y /z + echo %ARCH% > "%~dp0\grub\include\grub\cpu\%ARCH%" ) diff --git a/set_grub_cpu.sh b/set_grub_cpu.sh new file mode 100755 index 0000000..cee9192 --- /dev/null +++ b/set_grub_cpu.sh @@ -0,0 +1,13 @@ +#!/bin/bash +grub_include=`dirname $(readlink -f $0)`/grub/include/grub +shopt -s nocasematch +case "$1" in + "x64") arch=x86_64;; + "ia32") arch=i386;; + "arm") arch=arm;; + "aa64") arch=arm64;; + "aarch64") arch=arm64;; + *) echo "Unsupported arch"; exit 1;; +esac + rm -f $grub_include/cpu + ln -vs $grub_include/$arch $grub_include/cpu diff --git a/src/driver.h b/src/driver.h index fa0048b..0ea1f81 100644 --- a/src/driver.h +++ b/src/driver.h @@ -69,6 +69,13 @@ #endif #endif +/* Sort out the platform specifics */ +#if defined(_M_ARM64) || defined(__aarch64__) || defined (_M_X64) || defined(__x86_64__) +#define PERCENT_P L"%llx" +#else +#define PERCENT_P L"%x" +#endif + /* Sort out the differences between EDK2 and gnu-efi */ #if defined(_GNU_EFI) #define STUPID_CLANG_REF(a,b) a.b diff --git a/src/file.c b/src/file.c index 1538beb..2765af3 100644 --- a/src/file.c +++ b/src/file.c @@ -81,7 +81,7 @@ FileOpen(EFI_FILE_HANDLE This, EFI_FILE_HANDLE *New, INTN i, len; BOOLEAN AbsolutePath = (*Name == L'\\'); - PrintInfo(L"Open(%llx%s, \"%s\")\n", (UINT64) This, + PrintInfo(L"Open(" PERCENT_P L"%s, \"%s\")\n", (UINTN) This, IS_ROOT(File)?L" ":L"", Name); /* Fail unless opening read-only */ @@ -101,7 +101,7 @@ FileOpen(EFI_FILE_HANDLE This, EFI_FILE_HANDLE *New, PrintInfo(L" Reopening %s\n", IS_ROOT(File)?L"":FileName(File)); File->RefCount++; *New = This; - PrintInfo(L" RET: %llx\n", (UINT64) *New); + PrintInfo(L" RET: " PERCENT_P L"\n", (UINTN) *New); return EFI_SUCCESS; } @@ -138,7 +138,7 @@ FileOpen(EFI_FILE_HANDLE This, EFI_FILE_HANDLE *New, *New = &File->FileSystem->RootFile->EfiFile; /* Must make sure that DirIndex is reset too (NB: no concurrent access!) */ File->FileSystem->RootFile->DirIndex = 0; - PrintInfo(L" RET: %llx\n", (UINT64) *New); + PrintInfo(L" RET: " PERCENT_P L"\n", (UINTN) *New); return EFI_SUCCESS; } @@ -193,7 +193,7 @@ FileOpen(EFI_FILE_HANDLE This, EFI_FILE_HANDLE *New, NewFile->RefCount++; *New = &NewFile->EfiFile; - PrintInfo(L" RET: %llx\n", (UINT64) *New); + PrintInfo(L" RET: " PERCENT_P L"\n", (UINTN) *New); return EFI_SUCCESS; } @@ -217,7 +217,7 @@ FileClose(EFI_FILE_HANDLE This) { EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile); - PrintInfo(L"Close(%llx|'%s') %s\n", (UINT64) This, FileName(File), + PrintInfo(L"Close(" PERCENT_P L"|'%s') %s\n", (UINTN) This, FileName(File), IS_ROOT(File)?L"":L""); /* Nothing to do it this is the root */ @@ -405,7 +405,7 @@ FileRead(EFI_FILE_HANDLE This, UINTN *Len, VOID *Data) { EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile); - PrintInfo(L"Read(%llx|'%s', %d) %s\n", (UINT64) This, FileName(File), + PrintInfo(L"Read(" PERCENT_P L"|'%s', %d) %s\n", (UINTN) This, FileName(File), *Len, File->IsDir?L"":L""); /* If this is a directory, then fetch the directory entries */ @@ -459,7 +459,7 @@ FileSetPosition(EFI_FILE_HANDLE This, UINT64 Position) EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile); UINT64 FileSize; - PrintInfo(L"SetPosition(%llx|'%s', %lld) %s\n", (UINT64) This, + PrintInfo(L"SetPosition(" PERCENT_P L"|'%s', %lld) %s\n", (UINTN) This, FileName(File), Position, (File->IsDir)?L"":L""); /* If this is a directory, reset the Index to the start */ @@ -475,7 +475,7 @@ FileSetPosition(EFI_FILE_HANDLE This, UINT64 Position) */ FileSize = GrubGetFileSize(File); if (Position > FileSize) { - PrintError(L"'%s': Cannot seek to %#llx of %llx\n", + PrintError(L"'%s': Cannot seek to #%llx of %llx\n", FileName(File), Position, FileSize); return EFI_UNSUPPORTED; } @@ -500,7 +500,7 @@ FileGetPosition(EFI_FILE_HANDLE This, UINT64 *Position) { EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile); - PrintInfo(L"GetPosition(%llx|'%s', %lld)\n", (UINT64) This, FileName(File)); + PrintInfo(L"GetPosition(" PERCENT_P L"|'%s', %lld)\n", (UINTN) This, FileName(File)); if (File->IsDir) *Position = File->DirIndex; @@ -528,9 +528,9 @@ FileGetInfo(EFI_FILE_HANDLE This, EFI_GUID *Type, UINTN *Len, VOID *Data) EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *VLInfo = (EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *)Data; EFI_TIME Time; CHAR8* label; - INTN tmpLen; + UINTN tmpLen; - PrintInfo(L"GetInfo(%llx|'%s', %d) %s\n", (UINT64) This, + PrintInfo(L"GetInfo(" PERCENT_P L"|'%s', %d) %s\n", (UINTN) This, FileName(File), *Len, File->IsDir?L"":L""); /* Determine information to return */ @@ -558,7 +558,7 @@ FileGetInfo(EFI_FILE_HANDLE This, EFI_GUID *Type, UINTN *Len, VOID *Data) Info->PhysicalSize = GrubGetFileSize(File); } - tmpLen = (INTN)(Info->Size - sizeof(EFI_FILE_INFO) - 1); + tmpLen = (UINTN)(Info->Size - sizeof(EFI_FILE_INFO) - 1); Status = Utf8ToUtf16NoAllocUpdateLen(File->basename, Info->FileName, &tmpLen); if (EFI_ERROR(Status)) { if (Status != EFI_BUFFER_TOO_SMALL) @@ -683,7 +683,7 @@ FileFlush(EFI_FILE_HANDLE This) { EFI_GRUB_FILE *File = _CR(This, EFI_GRUB_FILE, EfiFile); - PrintInfo(L"Flush(%llx|'%s')\n", (UINT64) This, FileName(File)); + PrintInfo(L"Flush(" PERCENT_P L"|'%s')\n", (UINTN) This, FileName(File)); return EFI_SUCCESS; } diff --git a/src/logging.c b/src/logging.c index bcf0478..34ca653 100644 --- a/src/logging.c +++ b/src/logging.c @@ -74,7 +74,7 @@ SetLogging(VOID) LogLevel = Atoi(LogVar); for (i=0; i=0)?a:-a, _b = (b>=0)?b:-b; if (((a > 0) & (b < 0)) || ((a < 0) && (b > 0))) - return -MultU64x32(_a, (UINTN)_b); + return -1LL * MultU64x32(_a, (UINTN)_b); return MultU64x32(_a, (UINTN)_b); }