# 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)
#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
+0.6.13 (?/??/2013):
+-------------------
+
+
+
0.6.12 (6/18/2013):
-------------------
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
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.....
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)
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:
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) {
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) {
* 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;
// 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;
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
* 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;
// 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;
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;
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
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
*/
/*@{*/
-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);
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);
// 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);
#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;
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)
{
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");
// EFI OS loader functions
//
-static VOID StartLoader(IN LOADER_ENTRY *Entry)
+static VOID StartLoader(LOADER_ENTRY *Entry)
{
UINTN ErrorInStep = 0;
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
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);