From 4db5e22152813f5a21f7856f9e2121438bfab64d Mon Sep 17 00:00:00 2001 From: srs5694 Date: Sat, 22 Jun 2013 18:46:37 -0400 Subject: [PATCH] Btrfs driver & check for valid loader before adding to menu. --- Make.common | 18 +++++++------- NEWS.txt | 5 ++++ filesystems/Make.tiano | 2 +- filesystems/Makefile | 12 ++++++++-- filesystems/fsw_core.c | 34 ++++++++++++++++++++++++--- filesystems/fsw_core.h | 10 +++++--- filesystems/fsw_ext2.c | 4 ++-- filesystems/fsw_ext4.c | 4 ++-- mok/simple_file.c | 53 +++++++++++++++++++++++++++++++++++++++++- refind/main.c | 42 +++++++++++++++++++++++++++++++-- 10 files changed, 159 insertions(+), 25 deletions(-) diff --git a/Make.common b/Make.common index 0d994e5..55755e2 100644 --- a/Make.common +++ b/Make.common @@ -3,16 +3,16 @@ # Common make rules for building with gnu-efi # -EFIINC = /usr/include/efi -GNUEFILIB = /usr/lib64 -EFILIB = /usr/lib64 -EFICRT0 = /usr/lib64 +#EFIINC = /usr/include/efi +#GNUEFILIB = /usr/lib64 +#EFILIB = /usr/lib64 +#EFICRT0 = /usr/lib64 # Comment out above and uncomment below if using locally-compiled GNU-EFI.... -#EFIINC = /usr/local/include/efi -#GNUEFILIB = /usr/local/lib -#EFILIB = /usr/local/lib -#EFICRT0 = /usr/local/lib +EFIINC = /usr/local/include/efi +GNUEFILIB = /usr/local/lib +EFILIB = /usr/local/lib +EFICRT0 = /usr/local/lib HOSTARCH = $(shell uname -m | sed s,i[3456789]86,ia32,) ARCH := $(HOSTARCH) @@ -24,7 +24,7 @@ DEBUGFLAGS = -Wall #CFLAGS = $(ARCH3264) $(OPTIMFLAGS) -fpic -fshort-wchar $(DEBUGFLAGS) CFLAGS = $(ARCH3264) $(OPTIMFLAGS) -fno-stack-protector -fpic -fshort-wchar -mno-red-zone $(DEBUGFLAGS) ASFLAGS = $(ARCH3264) -LDFLAGS = -nostdlib -znocombreloc +LDFLAGS = -nostdlib -znocombreloc -zdefs prefix = /usr/bin/ CC = $(prefix)gcc diff --git a/NEWS.txt b/NEWS.txt index 1b9a439..e9cd6a0 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -1,3 +1,8 @@ +0.6.13 (?/??/2013): +------------------- + + + 0.6.12 (6/18/2013): ------------------- diff --git a/filesystems/Make.tiano b/filesystems/Make.tiano index 64266cd..b9ad0a8 100644 --- a/filesystems/Make.tiano +++ b/filesystems/Make.tiano @@ -14,7 +14,7 @@ ifeq ($(ARCH),ia64) endif ifeq ($(ARCH),ia32) - ARCH_C_FLAGS = -m32 -malign-double + ARCH_C_FLAGS = -m32 -malign-double -g ARCHDIR = Ia32 UC_ARCH = IA32 FILENAME_CODE = ia32 diff --git a/filesystems/Makefile b/filesystems/Makefile index cf60067..4aa838e 100644 --- a/filesystems/Makefile +++ b/filesystems/Makefile @@ -8,8 +8,8 @@ INSTALL_DIR = /boot/efi/EFI/refind/drivers -FILESYSTEMS = ext2 ext4 reiserfs iso9660 hfs -FILESYSTEMS_GNUEFI = ext2_gnuefi ext4_gnuefi reiserfs_gnuefi iso9660_gnuefi hfs_gnuefi +FILESYSTEMS = ext2 ext4 reiserfs iso9660 hfs btrfs +FILESYSTEMS_GNUEFI = ext2_gnuefi ext4_gnuefi reiserfs_gnuefi iso9660_gnuefi hfs_gnuefi btrfs_gnuefi TEXTFILES = $(FILESYSTEMS:=*.txt) # Build the drivers with TianoCore EDK2..... @@ -36,6 +36,10 @@ hfs: rm -f fsw_efi.obj +make DRIVERNAME=hfs -f Make.tiano +btrfs: + rm -f fsw_efi.obj + +make DRIVERNAME=btrfs -f Make.tiano + # Build the drivers with GNU-EFI.... gnuefi: $(FILESYSTEMS_GNUEFI) @@ -62,6 +66,10 @@ hfs_gnuefi: rm -f fsw_efi.o +make DRIVERNAME=hfs -f Make.gnuefi +btrfs_gnuefi: + rm -f fsw_efi.o + +make DRIVERNAME=btrfs -f Make.gnuefi + # utility rules clean: diff --git a/filesystems/fsw_core.c b/filesystems/fsw_core.c index 64d70d7..dbc7198 100644 --- a/filesystems/fsw_core.c +++ b/filesystems/fsw_core.c @@ -190,6 +190,21 @@ fsw_status_t fsw_block_get(struct VOLSTRUCTNAME *vol, fsw_u32 phys_bno, fsw_u32 if (cache_level > MAX_CACHE_LEVEL) cache_level = MAX_CACHE_LEVEL; + if (vol->bcache_size > 0 && vol->bcache == NULL) { + /* driver set the initial cache size */ + status = fsw_alloc(vol->bcache_size * sizeof(struct fsw_blockcache), &vol->bcache); + if(status) + return status; + for( i = 0; i < vol->bcache_size; i++) { + vol->bcache[i].refcount = 0; + vol->bcache[i].cache_level = 0; + vol->bcache[i].phys_bno = (fsw_u32)FSW_INVALID_BNO; + vol->bcache[i].data = NULL; + } + i = 0; + goto miss; + } + // check block cache for (i = 0; i < vol->bcache_size; i++) { if (vol->bcache[i].phys_bno == phys_bno) { @@ -243,6 +258,7 @@ fsw_status_t fsw_block_get(struct VOLSTRUCTNAME *vol, fsw_u32 phys_bno, fsw_u32 vol->bcache_size = new_bcache_size; } vol->bcache[i].phys_bno = (fsw_u32)FSW_INVALID_BNO; +miss: // read the data if (vol->bcache[i].data == NULL) { @@ -322,7 +338,7 @@ static void fsw_dnode_register(struct fsw_volume *vol, struct fsw_dnode *dno) * behaves in the same way as fsw_dnode_create. */ -fsw_status_t fsw_dnode_create_root(struct fsw_volume *vol, fsw_u32 dnode_id, struct fsw_dnode **dno_out) +fsw_status_t fsw_dnode_create_root_with_tree(struct fsw_volume *vol, fsw_u64 tree_id, fsw_u64 dnode_id, struct fsw_dnode **dno_out) { fsw_status_t status; struct fsw_dnode *dno; @@ -335,6 +351,7 @@ fsw_status_t fsw_dnode_create_root(struct fsw_volume *vol, fsw_u32 dnode_id, str // fill the structure dno->vol = vol; dno->parent = NULL; + dno->tree_id = tree_id; dno->dnode_id = dnode_id; dno->type = FSW_DNODE_TYPE_DIR; dno->refcount = 1; @@ -347,6 +364,10 @@ fsw_status_t fsw_dnode_create_root(struct fsw_volume *vol, fsw_u32 dnode_id, str return FSW_SUCCESS; } +fsw_status_t fsw_dnode_create_root(struct fsw_volume *vol, fsw_u64 dnode_id, struct fsw_dnode **dno_out) +{ + return fsw_dnode_create_root_with_tree( vol, 0, dnode_id, dno_out); +} /** * Create a new dnode representing a file system object. This function is called by * the file system driver in response to directory lookup or read requests. Note that @@ -365,7 +386,7 @@ fsw_status_t fsw_dnode_create_root(struct fsw_volume *vol, fsw_u32 dnode_id, str * that must be released by the caller with fsw_dnode_release. */ -fsw_status_t fsw_dnode_create(struct fsw_dnode *parent_dno, fsw_u32 dnode_id, int type, +fsw_status_t fsw_dnode_create_with_tree(struct fsw_dnode *parent_dno, fsw_u64 tree_id, fsw_u64 dnode_id, int type, struct fsw_string *name, struct fsw_dnode **dno_out) { fsw_status_t status; @@ -374,7 +395,7 @@ fsw_status_t fsw_dnode_create(struct fsw_dnode *parent_dno, fsw_u32 dnode_id, in // check if we already have a dnode with the same id for (dno = vol->dnode_head; dno; dno = dno->next) { - if (dno->dnode_id == dnode_id) { + if (dno->dnode_id == dnode_id && dno->tree_id == tree_id) { fsw_dnode_retain(dno); *dno_out = dno; return FSW_SUCCESS; @@ -390,6 +411,7 @@ fsw_status_t fsw_dnode_create(struct fsw_dnode *parent_dno, fsw_u32 dnode_id, in dno->vol = vol; dno->parent = parent_dno; fsw_dnode_retain(dno->parent); + dno->tree_id = tree_id; dno->dnode_id = dnode_id; dno->type = type; dno->refcount = 1; @@ -405,6 +427,12 @@ fsw_status_t fsw_dnode_create(struct fsw_dnode *parent_dno, fsw_u32 dnode_id, in return FSW_SUCCESS; } +fsw_status_t fsw_dnode_create(struct fsw_dnode *parent_dno, fsw_u64 dnode_id, int type, + struct fsw_string *name, struct fsw_dnode **dno_out) +{ + return fsw_dnode_create_with_tree(parent_dno, 0, dnode_id, type, name, dno_out); +} + /** * Increases the reference count of a dnode. This must be balanced with * fsw_dnode_release calls. Note that some dnode functions return a retained diff --git a/filesystems/fsw_core.h b/filesystems/fsw_core.h index 56eb58b..d8267e4 100644 --- a/filesystems/fsw_core.h +++ b/filesystems/fsw_core.h @@ -267,7 +267,8 @@ struct fsw_dnode { struct DNODESTRUCTNAME *parent; //!< Parent directory dnode struct fsw_string name; //!< Name of this item in the parent directory - fsw_u32 dnode_id; //!< Unique id number (usually the inode number) + fsw_u64 tree_id; //!< Unique id number (usually the btrfs subvolume) + fsw_u64 dnode_id; //!< Unique id number (usually the inode number) int type; //!< Type of the dnode - file, dir, symlink, special fsw_u64 size; //!< Data size in bytes @@ -419,8 +420,11 @@ void fsw_block_release(struct VOLSTRUCTNAME *vol, fsw_u32 phys_bno, void */ /*@{*/ -fsw_status_t fsw_dnode_create_root(struct VOLSTRUCTNAME *vol, fsw_u32 dnode_id, struct DNODESTRUCTNAME **dno_out); -fsw_status_t fsw_dnode_create(struct DNODESTRUCTNAME *parent_dno, fsw_u32 dnode_id, int type, +fsw_status_t fsw_dnode_create_root(struct VOLSTRUCTNAME *vol, fsw_u64 dnode_id, struct DNODESTRUCTNAME **dno_out); +fsw_status_t fsw_dnode_create(struct DNODESTRUCTNAME *parent_dno, fsw_u64 dnode_id, int type, + struct fsw_string *name, struct DNODESTRUCTNAME **dno_out); +fsw_status_t fsw_dnode_create_root_with_tree(struct VOLSTRUCTNAME *vol, fsw_u64 tree_id, fsw_u64 dnode_id, struct DNODESTRUCTNAME **dno_out); +fsw_status_t fsw_dnode_create_with_tree(struct DNODESTRUCTNAME *parent_dno, fsw_u64 tree_id, fsw_u64 dnode_id, int type, struct fsw_string *name, struct DNODESTRUCTNAME **dno_out); void fsw_dnode_retain(struct fsw_dnode *dno); void fsw_dnode_release(struct fsw_dnode *dno); diff --git a/filesystems/fsw_ext2.c b/filesystems/fsw_ext2.c index a6e88bf..1b68b99 100644 --- a/filesystems/fsw_ext2.c +++ b/filesystems/fsw_ext2.c @@ -204,8 +204,8 @@ static fsw_status_t fsw_ext2_dnode_fill(struct fsw_ext2_volume *vol, struct fsw_ FSW_MSG_DEBUG((FSW_MSGSTR("fsw_ext2_dnode_fill: inode %d\n"), dno->g.dnode_id)); // read the inode block - groupno = (dno->g.dnode_id - 1) / vol->sb->s_inodes_per_group; - ino_in_group = (dno->g.dnode_id - 1) % vol->sb->s_inodes_per_group; + groupno = (fsw_u32) (dno->g.dnode_id - 1) / vol->sb->s_inodes_per_group; + ino_in_group = (fsw_u32) (dno->g.dnode_id - 1) % vol->sb->s_inodes_per_group; ino_bno = vol->inotab_bno[groupno] + ino_in_group / (vol->g.phys_blocksize / vol->inode_size); ino_index = ino_in_group % (vol->g.phys_blocksize / vol->inode_size); diff --git a/filesystems/fsw_ext4.c b/filesystems/fsw_ext4.c index 42f136d..0beaa4d 100644 --- a/filesystems/fsw_ext4.c +++ b/filesystems/fsw_ext4.c @@ -279,8 +279,8 @@ static fsw_status_t fsw_ext4_dnode_fill(struct fsw_ext4_volume *vol, struct fsw_ // read the inode block - groupno = (dno->g.dnode_id - 1) / vol->sb->s_inodes_per_group; - ino_in_group = (dno->g.dnode_id - 1) % vol->sb->s_inodes_per_group; + groupno = (fsw_u32) (dno->g.dnode_id - 1) / vol->sb->s_inodes_per_group; + ino_in_group = (fsw_u32) (dno->g.dnode_id - 1) % vol->sb->s_inodes_per_group; ino_bno = vol->inotab_bno[groupno] + ino_in_group / (vol->g.phys_blocksize / vol->inode_size); ino_index = ino_in_group % (vol->g.phys_blocksize / vol->inode_size); diff --git a/mok/simple_file.c b/mok/simple_file.c index 0637305..263593f 100644 --- a/mok/simple_file.c +++ b/mok/simple_file.c @@ -8,7 +8,7 @@ #include "../include/refit_call_wrapper.h" #include "simple_file.h" -#include "execute.h" /* for generate_path() */ +//#include "execute.h" /* for generate_path() */ static EFI_GUID IMAGE_PROTOCOL = LOADED_IMAGE_PROTOCOL; static EFI_GUID SIMPLE_FS_PROTOCOL = SIMPLE_FILE_SYSTEM_PROTOCOL; @@ -43,6 +43,57 @@ simple_file_open_by_handle(EFI_HANDLE device, CHAR16 *name, EFI_FILE **file, UIN return efi_status; } +// generate_path() from shim by Matthew J. Garrett +static +EFI_STATUS +generate_path(CHAR16* name, EFI_LOADED_IMAGE *li, EFI_DEVICE_PATH **path, CHAR16 **PathName) +{ + unsigned int pathlen; + EFI_STATUS efi_status = EFI_SUCCESS; + CHAR16 *devpathstr = DevicePathToStr(li->FilePath), + *found = NULL; + int i; + + for (i = 0; i < StrLen(devpathstr); i++) { + if (devpathstr[i] == '/') + devpathstr[i] = '\\'; + if (devpathstr[i] == '\\') + found = &devpathstr[i]; + } + if (!found) { + pathlen = 0; + } else { + while (*(found - 1) == '\\') + --found; + *found = '\0'; + pathlen = StrLen(devpathstr); + } + + if (name[0] != '\\') + pathlen++; + + *PathName = AllocatePool((pathlen + 1 + StrLen(name))*sizeof(CHAR16)); + + if (!*PathName) { + Print(L"Failed to allocate path buffer\n"); + efi_status = EFI_OUT_OF_RESOURCES; + goto error; + } + + StrCpy(*PathName, devpathstr); + + if (name[0] != '\\') + StrCat(*PathName, L"\\"); + StrCat(*PathName, name); + + *path = FileDevicePath(li->DeviceHandle, *PathName); + +error: + FreePool(devpathstr); + + return efi_status; +} // generate_path() + EFI_STATUS simple_file_open(EFI_HANDLE image, CHAR16 *name, EFI_FILE **file, UINT64 mode) { diff --git a/refind/main.c b/refind/main.c index 2e4e0d4..b6029b9 100644 --- a/refind/main.c +++ b/refind/main.c @@ -144,7 +144,7 @@ static VOID AboutrEFInd(VOID) if (AboutMenu.EntryCount == 0) { AboutMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT); - AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.6.12"); + AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.6.12.1"); AddMenuInfoLine(&AboutMenu, L""); AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2006-2010 Christoph Pfisterer"); AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012-2013 Roderick W. Smith"); @@ -383,7 +383,7 @@ static EFI_STATUS RebootIntoFirmware(VOID) { // EFI OS loader functions // -static VOID StartLoader(IN LOADER_ENTRY *Entry) +static VOID StartLoader(LOADER_ENTRY *Entry) { UINTN ErrorInStep = 0; @@ -1161,6 +1161,38 @@ static BOOLEAN IsSymbolicLink(REFIT_VOLUME *Volume, CHAR16 *Path, EFI_FILE_INFO return (DirEntry->FileSize != FileSize2); } // BOOLEAN IsSymbolicLink() +// Returns TRUE if this file is a valid EFI loader file, and is proper ARCH +static BOOLEAN IsValidLoader(REFIT_VOLUME *Volume, CHAR16 *FileName) { +#if defined (EFIX64) +#define EFI_STUB_ARCH 0x8664 +#else +#define EFI_STUB_ARCH 0x14c +#endif +#define FAT_ARCH 0x0ef1fab9 /* ID for Apple "fat" binary */ + EFI_STATUS Status; + EFI_FILE_HANDLE FileHandle; + CHAR8 Header[512]; + UINTN Size = sizeof(Header); + BOOLEAN IsValid; + + Status = refit_call5_wrapper(Volume->RootDir->Open, Volume->RootDir, &FileHandle, FileName, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR(Status)) + return 0; + + Status = refit_call3_wrapper(FileHandle->Read, FileHandle, &Size, Header); + refit_call1_wrapper(FileHandle->Close, FileHandle); + + IsValid = !EFI_ERROR(Status) && + Size == sizeof(Header) && + ((Header[0] == 'M' && Header[1] == 'Z' && + (Size = *(UINT32 *)&Header[0x3c]) < 0x180 && + Header[Size] == 'P' && Header[Size+1] == 'E' && + Header[Size+2] == 0 && Header[Size+3] == 0 && + *(UINT16 *)&Header[Size+4] == EFI_STUB_ARCH) || + (*(UINT32 *)&Header == FAT_ARCH)); + return IsValid; +} // BOOLEAN IsValidLoader() + // Scan an individual directory for EFI boot loader files and, if found, // add them to the list. Exception: Ignores FALLBACK_FULLNAME, which is picked // up in ScanEfiFiles(). Sorts the entries within the loader directory so that @@ -1196,6 +1228,12 @@ static BOOLEAN ScanLoaderDir(IN REFIT_VOLUME *Volume, IN CHAR16 *Path, IN CHAR16 else SPrint(FileName, 255, L"\\%s", DirEntry->FileName); CleanUpPathNameSlashes(FileName); + + if( /* (!StriSubCmp(L"vmlinuz", DirEntry->FileName) || + !StriSubCmp(L"bzImage", DirEntry->FileName)) && */ + !IsValidLoader(Volume, FileName)) + continue; + NewLoader = AllocateZeroPool(sizeof(struct LOADER_LIST)); if (NewLoader != NULL) { NewLoader->FileName = StrDuplicate(FileName); -- 2.39.2