localfs.c
来自「EFI(Extensible Firmware Interface)是下一代BI」· C语言 代码 · 共 298 行
C
298 行
/* * Copyright (C) 2001-2003 Hewlett-Packard Co. * Contributed by Stephane Eranian <eranian@hpl.hp.com> * * This file is part of the ELILO, the EFI Linux boot loader. * * ELILO is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * ELILO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ELILO; see the file COPYING. If not, write to the Free * Software Foundation, 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * * Please check out the elilo.txt for complete documentation on how * to use this program. */#include <efi.h>#include <efilib.h>#include "elilo.h"#include "fs/localfs.h"/* * LocalFS is just a shim layer on top of the * FileSystem Protocol which gives access to FAT32,16,12 */#define FS_NAME L"vfat"typedef struct { EFI_HANDLE dev; /* device we're attached to */ EFI_FILE_HANDLE volume; /* root of volume */} localfs_priv_state_t;#define LOCALFS_F2FD(f) ((UINTN)(f))#define LOCALFS_FD2F(fd) ((EFI_FILE_HANDLE)(fd))typedef union { localfs_interface_t pub_intf; struct { localfs_interface_t pub_intf; localfs_priv_state_t priv_data; } localfs_priv;} localfs_t;#define FS_PRIVATE(n) (&(((localfs_t *)n)->localfs_priv.priv_data))static EFI_GUID LocalFsProtocol = LOCALFS_PROTOCOL;/* * let's be clean here */typedef union { EFI_HANDLE *dev; localfs_t *intf;} dev_tab_t;static dev_tab_t *dev_tab; /* holds all devices we found */static UINTN ndev; /* how many entries in dev_tab */static EFI_STATUSlocalfs_name(localfs_interface_t *this, CHAR16 *name, UINTN maxlen){ if (name == NULL || maxlen < 1) return EFI_INVALID_PARAMETER; StrnCpy(name, FS_NAME, maxlen-1); name[maxlen-1] = CHAR_NULL; return EFI_SUCCESS;}static EFI_STATUSlocalfs_open(localfs_interface_t *this, CHAR16 *name, UINTN *fd){ localfs_priv_state_t *lfs; EFI_STATUS status; EFI_FILE_HANDLE fh; if (this == NULL || name == NULL || fd == NULL) return EFI_INVALID_PARAMETER; lfs = FS_PRIVATE(this); DBG_PRT((L"localfs_open on %s\n", name)); status = lfs->volume->Open(lfs->volume, &fh, name, EFI_FILE_MODE_READ, 0); if (status == EFI_SUCCESS) { *fd = LOCALFS_F2FD(fh); } return status;}static EFI_STATUSlocalfs_read(localfs_interface_t *this, UINTN fd, VOID *buf, UINTN *size){ localfs_priv_state_t *lfs; if (this == NULL || fd == 0 || buf == NULL || size == NULL) return EFI_INVALID_PARAMETER; lfs = FS_PRIVATE(this); return lfs->volume->Read(LOCALFS_FD2F(fd), size, buf);}static EFI_STATUSlocalfs_close(localfs_interface_t *this, UINTN fd){ localfs_priv_state_t *lfs; if (this == NULL || fd == 0) return EFI_INVALID_PARAMETER; lfs = FS_PRIVATE(this); return lfs->volume->Close(LOCALFS_FD2F(fd));}static EFI_STATUSlocalfs_infosize(localfs_interface_t *this, UINTN fd, UINT64 *sz){ localfs_priv_state_t *lfs; EFI_FILE_INFO *info; if (this == NULL || fd == 0 || sz == NULL) return EFI_INVALID_PARAMETER; lfs = FS_PRIVATE(this); info = LibFileInfo(LOCALFS_FD2F(fd)); if (info == NULL) return EFI_UNSUPPORTED; *sz = info->FileSize; FreePool(info); return EFI_SUCCESS;}static EFI_STATUSlocalfs_seek(localfs_interface_t *this, UINTN fd, UINT64 newpos){ localfs_priv_state_t *lfs; if (this == NULL || fd == 0) return EFI_INVALID_PARAMETER; lfs = FS_PRIVATE(this); return lfs->volume->SetPosition(LOCALFS_FD2F(fd), newpos);}static VOIDlocalfs_init_state(localfs_t *localfs, EFI_HANDLE dev, EFI_FILE_HANDLE volume){ localfs_priv_state_t *lfs = FS_PRIVATE(localfs); /* need to do some init here on localfs_intf */ Memset(localfs, 0, sizeof(*localfs)); localfs->pub_intf.localfs_name = localfs_name; localfs->pub_intf.localfs_open = localfs_open; localfs->pub_intf.localfs_read = localfs_read; localfs->pub_intf.localfs_close = localfs_close; localfs->pub_intf.localfs_infosize = localfs_infosize; localfs->pub_intf.localfs_seek = localfs_seek; lfs->dev = dev; lfs->volume = volume;}static EFI_STATUSlocalfs_install_one(EFI_HANDLE dev, VOID **intf){ EFI_STATUS status; localfs_t *localfs; EFI_FILE_IO_INTERFACE *volume; EFI_FILE_HANDLE volume_fh; status = BS->HandleProtocol (dev, &LocalFsProtocol, (VOID **)&localfs); if (status == EFI_SUCCESS) { ERR_PRT((L"Warning: found existing %s protocol on device", FS_NAME)); goto found; } status = BS->HandleProtocol (dev, &FileSystemProtocol, (VOID **)&volume); if (EFI_ERROR(status)) return EFI_INVALID_PARAMETER; status = volume->OpenVolume(volume, &volume_fh); if (EFI_ERROR(status)) { ERR_PRT((L"cannot open volume")); return status; } localfs = (localfs_t *)alloc(sizeof(*localfs), EfiLoaderData); if (localfs == NULL) { ERR_PRT((L"failed to allocate %s", FS_NAME)); return EFI_OUT_OF_RESOURCES; } localfs_init_state(localfs, dev, volume_fh); status = LibInstallProtocolInterfaces(&dev, &LocalFsProtocol, localfs, NULL); if (EFI_ERROR(status)) { ERR_PRT((L"Cannot install %s protocol: %r", FS_NAME, status)); free(localfs); return status; }found: if (intf) *intf = (VOID *)localfs; VERB_PRT(3, { EFI_DEVICE_PATH *dp; CHAR16 *str; dp = DevicePathFromHandle(dev); str = DevicePathToStr(dp); Print(L"attached %s to %s\n", FS_NAME, str); FreePool(str); }); return EFI_SUCCESS;} EFI_STATUSlocalfs_install(VOID){ UINTN size = 0; UINTN i; EFI_STATUS status; VOID *intf; BS->LocateHandle(ByProtocol, &FileSystemProtocol, NULL, &size, NULL); if (size == 0) return EFI_UNSUPPORTED; /* no device found, oh well */ DBG_PRT((L"size=%d", size)); dev_tab = (dev_tab_t *)alloc(size, EfiLoaderData); if (dev_tab == NULL) { ERR_PRT((L"failed to allocate handle table")); return EFI_OUT_OF_RESOURCES; } status = BS->LocateHandle(ByProtocol, &FileSystemProtocol, NULL, &size, (VOID **)dev_tab); if (status != EFI_SUCCESS) { ERR_PRT((L"failed to get handles: %r", status)); free(dev_tab); return status; } ndev = size / sizeof(EFI_HANDLE); for(i=0; i < ndev; i++) { intf = NULL; localfs_install_one(dev_tab[i].dev, &intf); /* override device handle with interface pointer */ dev_tab[i].intf = intf; } return EFI_SUCCESS;} EFI_STATUSlocalfs_uninstall(VOID){ localfs_priv_state_t *lfs; EFI_STATUS status; UINTN i; for(i=0; i < ndev; i++) { if (dev_tab[i].intf == NULL) continue; lfs = FS_PRIVATE(dev_tab[i].intf); status = BS->UninstallProtocolInterface(lfs->dev, &LocalFsProtocol, dev_tab[i].intf); if (EFI_ERROR(status)) { ERR_PRT((L"Uninstall %s error: %r", FS_NAME, status)); continue; } VERB_PRT(3, { EFI_DEVICE_PATH *dp; CHAR16 *str; dp = DevicePathFromHandle(lfs->dev); str = DevicePathToStr(dp); Print(L"uninstalled %s on %s\n", FS_NAME, str); FreePool(str); }); free(dev_tab[i].intf); } if (dev_tab) free(dev_tab); return EFI_SUCCESS;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?