Skip to content

Commit

Permalink
move path related functions into their own source
Browse files Browse the repository at this point in the history
* Also fix Makefile builds
  • Loading branch information
pbatard committed Sep 23, 2021
1 parent 77577c7 commit 874cdec
Show file tree
Hide file tree
Showing 6 changed files with 219 additions and 184 deletions.
1 change: 1 addition & 0 deletions .vs/uefi-ntfs.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,7 @@ echo #define VERSION_STRING L"%VERSION%"&gt; $(SolutionDir)version.h</Command>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\boot.c" />
<ClCompile Include="..\path.c" />
</ItemGroup>
<ItemGroup>
<None Include="..\debug.vbs" />
Expand Down
3 changes: 3 additions & 0 deletions .vs/uefi-ntfs.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
<ClCompile Include="..\boot.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\path.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\boot.h">
Expand Down
15 changes: 10 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ CFLAGS += -DCONFIG_$(GNUEFI_ARCH) -D__MAKEWITH_GNUEFI -DGNU_EFI_USE_MS_A
LDFLAGS += -L$(GNUEFI_DIR)/$(GNUEFI_ARCH)/lib -e $(EP_PREFIX)efi_main
LDFLAGS += -s -Wl,-Bsymbolic -nostdlib -shared
LIBS = -lefi $(CRT0_LIBS)
OBJS = boot.o path.o

ifeq (, $(shell which $(CC)))
$(error The selected compiler ($(CC)) was not found)
Expand All @@ -126,18 +127,22 @@ all: $(GNUEFI_DIR)/$(GNUEFI_ARCH)/lib/libefi.a boot.efi
$(GNUEFI_DIR)/$(GNUEFI_ARCH)/lib/libefi.a:
$(MAKE) -C$(GNUEFI_DIR) CROSS_COMPILE=$(CROSS_COMPILE) ARCH=$(GNUEFI_ARCH) $(GNUEFI_LIBS)

%.efi: %.o
version.h:
@echo [GEN] $(notdir $@)
@echo '#define VERSION_STRING L"$(shell git describe --tags --dirty)"' > version.h

%.efi: $(OBJS)
@echo [LD] $(notdir $@)
ifeq ($(CRT0_LIBS),)
@$(CC) $(LDFLAGS) $< -o $@ $(LIBS)
@$(CC) $(LDFLAGS) $(OBJS) -o $@ $(LIBS)
else
@$(CC) $(LDFLAGS) $< -o $*.elf $(LIBS)
@$(CC) $(LDFLAGS) $(OBJS) -o $*.elf $(LIBS)
@$(OBJCOPY) -j .text -j .sdata -j .data -j .dynamic -j .dynsym -j .rel* \
-j .rela* -j .reloc -j .eh_frame -O binary $*.elf $@
@rm -f $*.elf
endif

%.o: %.c
%.o: %.c version.h
@echo [CC] $(notdir $@)
@$(CC) $(CFLAGS) -ffreestanding -c $<

Expand Down Expand Up @@ -170,7 +175,7 @@ OVMF_$(OVMF_ARCH).fd:
rm $(OVMF_ZIP)

clean:
rm -f boot.efi *.o
rm -f version.h boot.efi *.o
rm -rf image

superclean: clean
Expand Down
178 changes: 19 additions & 159 deletions boot.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/*
* uefi-ntfs: UEFI → NTFS/exFAT chain loader
* Copyright © 2014-2021 Pete Batard <[email protected]>
* With parts from GRUB © 2006 Free Software Foundation, Inc.
* With parts from rEFInd © 2012-2016 Roderick W. Smith
*
* This program is free software: you can redistribute it and/or modify
Expand Down Expand Up @@ -29,164 +28,25 @@ static EFI_HANDLE MainImageHandle = NULL;
/* Tri-state status for Secure Boot: -1 = Setup, 0 = Disabled, 1 = Enabled */
static INTN SecureBootStatus = 0;

/* Return the device path node right before the end node */
static EFI_DEVICE_PATH* GetLastDevicePath(CONST EFI_DEVICE_PATH_PROTOCOL* dp)
{
EFI_DEVICE_PATH *next, *p;

if (IsDevicePathEnd(dp))
return NULL;

for (p = (EFI_DEVICE_PATH *) dp, next = NextDevicePathNode(p);
!IsDevicePathEnd(next);
p = next, next = NextDevicePathNode(next));

return p;
}

/*
* Get the parent device in an EFI_DEVICE_PATH
* Note: the returned device path is allocated and must be freed
*/
static EFI_DEVICE_PATH* GetParentDevice(CONST EFI_DEVICE_PATH* DevicePath)
{
EFI_DEVICE_PATH *dp, *ldp;

dp = DuplicateDevicePath((EFI_DEVICE_PATH*)DevicePath);
if (dp == NULL)
return NULL;

ldp = GetLastDevicePath(dp);
if (ldp == NULL)
return NULL;

ldp->Type = END_DEVICE_PATH_TYPE;
ldp->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE;

SetDevicePathNodeLength(ldp, sizeof (*ldp));

return dp;
}

/*
* Compare two device paths for equality.
*
* Note that this code was derived from the the GPLv2+ version of compare_device_paths() found at:
* https://git.savannah.gnu.org/cgit/grub.git/tree/disk/efi/efidisk.c?id=3572d015fdd9bbd1d17bc45a1f0f0b749e7a3d38#n92
*/
static INTN CompareDevicePaths(CONST EFI_DEVICE_PATH *dp1, CONST EFI_DEVICE_PATH *dp2)
{
if (dp1 == NULL || dp2 == NULL)
return -1;

while (1) {
UINT8 type1, type2;
UINT8 subtype1, subtype2;
UINT16 len1, len2;
INTN ret;

type1 = DevicePathType(dp1);
type2 = DevicePathType(dp2);

if (type1 != type2)
return (int) type2 - (int) type1;

subtype1 = DevicePathSubType(dp1);
subtype2 = DevicePathSubType(dp2);

if (subtype1 != subtype2)
return (int) subtype1 - (int) subtype2;

len1 = DevicePathNodeLength(dp1);
len2 = DevicePathNodeLength(dp2);
if (len1 != len2)
return (int) len1 - (int) len2;

ret = CompareMem(dp1, dp2, len1);
if (ret != 0)
return ret;

if (IsDevicePathEnd(dp1))
break;

dp1 = (EFI_DEVICE_PATH*) ((char *)dp1 + len1);
dp2 = (EFI_DEVICE_PATH*) ((char *)dp2 + len2);
}

return 0;
}

/*
* Some UEFI firmwares have a *BROKEN* Unicode collation implementation
* so we must provide our own version of StriCmp for ASCII comparison...
*/
static CHAR16 _tolower(CONST CHAR16 c)
{
if(('A' <= c) && (c <= 'Z'))
return 'a' + (c - 'A');
return c;
}

static INTN _StriCmp(CONST CHAR16 *s1, CONST CHAR16 *s2)
{
while ((*s1 != L'\0') && (_tolower(*s1) == _tolower(*s2)))
s1++, s2++;
return (INTN)(*s1 - *s2);
}

/* Fix the case of a path by looking it up on the file system */
static EFI_STATUS SetPathCase(CONST EFI_FILE_HANDLE Root, CHAR16* Path)
{
EFI_FILE_HANDLE FileHandle = NULL;
EFI_FILE_INFO* FileInfo;
UINTN i, Len;
UINTN Size;
EFI_STATUS Status;

if ((Root == NULL) || (Path == NULL) || (Path[0] != L'\\'))
return EFI_INVALID_PARAMETER;

FileInfo = (EFI_FILE_INFO*)AllocatePool(FILE_INFO_SIZE);
if (FileInfo == NULL)
return EFI_OUT_OF_RESOURCES;

Len = StrLen(Path);
// Find the last backslash in the path
for (i = Len-1; (i != 0) && (Path[i] != L'\\'); i--);

if (i != 0) {
Path[i] = 0;
// Recursively fix the case
Status = SetPathCase(Root, Path);
if (EFI_ERROR(Status))
goto out;
}

Status = Root->Open(Root, &FileHandle, (i==0)?L"\\":Path, EFI_FILE_MODE_READ, 0);
if (EFI_ERROR(Status))
goto out;

do {
Size = FILE_INFO_SIZE;
ZeroMem(FileInfo, Size);
Status = FileHandle->Read(FileHandle, &Size, (VOID*)FileInfo);
if (EFI_ERROR(Status))
goto out;
if (_StriCmp(&Path[i+1], FileInfo->FileName) == 0) {
StrCpy(&Path[i+1], FileInfo->FileName);
Status = EFI_SUCCESS;
goto out;
}
Status = EFI_NOT_FOUND;
} while (Size != 0);

out:
Path[i] = L'\\';
if (FileHandle != NULL)
FileHandle->Close(FileHandle);
FreePool((VOID*)FileInfo);
return Status;
}
/* Strings used to identify the plaform */
#if defined(_M_X64) || defined(__x86_64__)
static CHAR16* Arch = L"x64";
static CHAR16* ArchName = L"64-bit x86";
#elif defined(_M_IX86) || defined(__i386__)
static CHAR16* Arch = L"ia32";
static CHAR16* ArchName = L"32-bit x86";
#elif defined (_M_ARM64) || defined(__aarch64__)
static CHAR16* Arch = L"aa64";
static CHAR16* ArchName = L"64-bit ARM";
#elif defined (_M_ARM) || defined(__arm__)
static CHAR16* Arch = L"arm";
static CHAR16* ArchName = L"32-bit ARM";
#elif defined(_M_RISCV64) || (defined (__riscv) && (__riscv_xlen == 64))
static CHAR16* Arch = L"riscv64";
static CHAR16* ArchName = L"64-bit RISC-V";
#else
# error Unsupported architecture
#endif

/* Get the driver name from a driver handle */
static CHAR16* GetDriverName(CONST EFI_HANDLE DriverHandle)
Expand Down
45 changes: 25 additions & 20 deletions boot.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,26 +38,6 @@
/* FreePool() replacement, that NULLs the freed pointer. */
#define SafeFree(p) do { FreePool(p); p = NULL;} while(0)

/* Strings that can be used to identify the plaform */
#if defined(_M_X64) || defined(__x86_64__)
static CHAR16* Arch = L"x64";
static CHAR16* ArchName = L"64-bit x86";
#elif defined(_M_IX86) || defined(__i386__)
static CHAR16* Arch = L"ia32";
static CHAR16* ArchName = L"32-bit x86";
#elif defined (_M_ARM64) || defined(__aarch64__)
static CHAR16* Arch = L"aa64";
static CHAR16* ArchName = L"64-bit ARM";
#elif defined (_M_ARM) || defined(__arm__)
static CHAR16* Arch = L"arm";
static CHAR16* ArchName = L"32-bit ARM";
#elif defined(_M_RISCV64) || (defined (__riscv) && (__riscv_xlen == 64))
static CHAR16* Arch = L"riscv64";
static CHAR16* ArchName = L"64-bit RISC-V";
#else
# error Unsupported architecture
#endif

/*
* Convenience macros to print informational, warning or error messages.
* NB: In addition to the standard %-based flags, Print() supports the following:
Expand All @@ -71,3 +51,28 @@
#define PrintInfo(fmt, ...) Print(L"[INFO] " fmt L"\n", ##__VA_ARGS__)
#define PrintWarning(fmt, ...) Print(L"%E[WARN] " fmt L"%N\n", ##__VA_ARGS__)
#define PrintError(fmt, ...) Print(L"%E[FAIL] " fmt L": [%d] %r%N\n", ##__VA_ARGS__, (Status&0x7FFFFFFF), Status)

/*
* Some UEFI firmwares have a *BROKEN* Unicode collation implementation
* so we must provide our own version of StriCmp for ASCII comparison...
*/
static __inline CHAR16 _tolower(CONST CHAR16 c)
{
if (('A' <= c) && (c <= 'Z'))
return 'a' + (c - 'A');
return c;
}

static __inline INTN _StriCmp(CONST CHAR16 * s1, CONST CHAR16 * s2)
{
while ((*s1 != L'\0') && (_tolower(*s1) == _tolower(*s2)))
s1++, s2++;
return (INTN)(*s1 - *s2);
}

/*
* Path function prototypes
*/
EFI_DEVICE_PATH* GetParentDevice(CONST EFI_DEVICE_PATH* DevicePath);
INTN CompareDevicePaths(CONST EFI_DEVICE_PATH* dp1, CONST EFI_DEVICE_PATH* dp2);
EFI_STATUS SetPathCase(CONST EFI_FILE_HANDLE Root, CHAR16* Path);
Loading

0 comments on commit 874cdec

Please sign in to comment.