2 * Copyright (C) 2001-2003 Hewlett-Packard Co.
3 * Contributed by Stephane Eranian <eranian@hpl.hp.com>
5 * This file is part of the ELILO, the EFI Linux boot loader.
7 * ELILO is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
12 * ELILO is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with ELILO; see the file COPYING. If not, write to the Free
19 * Software Foundation, 59 Temple Place - Suite 330, Boston, MA
22 * Please check out the elilo.txt for complete documentation on how
23 * to use this program.
30 #include "fs/localfs.h"
33 * LocalFS is just a shim layer on top of the
34 * FileSystem Protocol which gives access to FAT32,16,12
36 #define FS_NAME L"vfat"
40 EFI_HANDLE dev; /* device we're attached to */
41 EFI_FILE_HANDLE volume; /* root of volume */
42 } localfs_priv_state_t;
44 #define LOCALFS_F2FD(f) ((UINTN)(f))
45 #define LOCALFS_FD2F(fd) ((EFI_FILE_HANDLE)(fd))
48 localfs_interface_t pub_intf;
50 localfs_interface_t pub_intf;
51 localfs_priv_state_t priv_data;
55 #define FS_PRIVATE(n) (&(((localfs_t *)n)->localfs_priv.priv_data))
58 static EFI_GUID LocalFsProtocol = LOCALFS_PROTOCOL;
68 static dev_tab_t *dev_tab; /* holds all devices we found */
69 static UINTN ndev; /* how many entries in dev_tab */
72 localfs_name(localfs_interface_t *this, CHAR16 *name, UINTN maxlen)
74 if (name == NULL || maxlen < 1) return EFI_INVALID_PARAMETER;
76 StrnCpy(name, FS_NAME, maxlen-1);
78 name[maxlen-1] = CHAR_NULL;
85 localfs_open(localfs_interface_t *this, CHAR16 *name, UINTN *fd)
87 localfs_priv_state_t *lfs;
91 if (this == NULL || name == NULL || fd == NULL) return EFI_INVALID_PARAMETER;
93 lfs = FS_PRIVATE(this);
95 DBG_PRT((L"localfs_open on %s\n", name));
97 status = lfs->volume->Open(lfs->volume, &fh, name, EFI_FILE_MODE_READ, 0);
98 if (status == EFI_SUCCESS) {
99 *fd = LOCALFS_F2FD(fh);
105 localfs_read(localfs_interface_t *this, UINTN fd, VOID *buf, UINTN *size)
107 localfs_priv_state_t *lfs;
109 if (this == NULL || fd == 0 || buf == NULL || size == NULL) return EFI_INVALID_PARAMETER;
111 lfs = FS_PRIVATE(this);
113 return lfs->volume->Read(LOCALFS_FD2F(fd), size, buf);
117 localfs_close(localfs_interface_t *this, UINTN fd)
119 localfs_priv_state_t *lfs;
121 if (this == NULL || fd == 0) return EFI_INVALID_PARAMETER;
123 lfs = FS_PRIVATE(this);
125 return lfs->volume->Close(LOCALFS_FD2F(fd));
129 localfs_infosize(localfs_interface_t *this, UINTN fd, UINT64 *sz)
131 localfs_priv_state_t *lfs;
134 if (this == NULL || fd == 0 || sz == NULL) return EFI_INVALID_PARAMETER;
136 lfs = FS_PRIVATE(this);
138 info = LibFileInfo(LOCALFS_FD2F(fd));
139 if (info == NULL) return EFI_UNSUPPORTED;
141 *sz = info->FileSize;
149 localfs_seek(localfs_interface_t *this, UINTN fd, UINT64 newpos)
151 localfs_priv_state_t *lfs;
153 if (this == NULL || fd == 0) return EFI_INVALID_PARAMETER;
155 lfs = FS_PRIVATE(this);
157 return lfs->volume->SetPosition(LOCALFS_FD2F(fd), newpos);
161 localfs_init_state(localfs_t *localfs, EFI_HANDLE dev, EFI_FILE_HANDLE volume)
163 localfs_priv_state_t *lfs = FS_PRIVATE(localfs);
165 /* need to do some init here on localfs_intf */
166 Memset(localfs, 0, sizeof(*localfs));
168 localfs->pub_intf.localfs_name = localfs_name;
169 localfs->pub_intf.localfs_open = localfs_open;
170 localfs->pub_intf.localfs_read = localfs_read;
171 localfs->pub_intf.localfs_close = localfs_close;
172 localfs->pub_intf.localfs_infosize = localfs_infosize;
173 localfs->pub_intf.localfs_seek = localfs_seek;
176 lfs->volume = volume;
180 localfs_install_one(EFI_HANDLE dev, VOID **intf)
185 EFI_FILE_IO_INTERFACE *volume;
186 EFI_FILE_HANDLE volume_fh;
188 status = BS->HandleProtocol (dev, &LocalFsProtocol, (VOID **)&localfs);
189 if (status == EFI_SUCCESS) {
190 ERR_PRT((L"Warning: found existing %s protocol on device", FS_NAME));
194 status = BS->HandleProtocol (dev, &FileSystemProtocol, (VOID **)&volume);
195 if (EFI_ERROR(status)) return EFI_INVALID_PARAMETER;
197 status = volume->OpenVolume(volume, &volume_fh);
198 if (EFI_ERROR(status)) {
199 ERR_PRT((L"cannot open volume"));
203 localfs = (localfs_t *)alloc(sizeof(*localfs), EfiLoaderData);
204 if (localfs == NULL) {
205 ERR_PRT((L"failed to allocate %s", FS_NAME));
206 return EFI_OUT_OF_RESOURCES;
208 localfs_init_state(localfs, dev, volume_fh);
210 status = LibInstallProtocolInterfaces(&dev, &LocalFsProtocol, localfs, NULL);
211 if (EFI_ERROR(status)) {
212 ERR_PRT((L"Cannot install %s protocol: %r", FS_NAME, status));
217 if (intf) *intf = (VOID *)localfs;
220 { EFI_DEVICE_PATH *dp; CHAR16 *str;
221 dp = DevicePathFromHandle(dev);
222 str = DevicePathToStr(dp);
223 Print(L"attached %s to %s\n", FS_NAME, str);
231 localfs_install(VOID)
238 BS->LocateHandle(ByProtocol, &FileSystemProtocol, NULL, &size, NULL);
239 if (size == 0) return EFI_UNSUPPORTED; /* no device found, oh well */
241 DBG_PRT((L"size=%d", size));
243 dev_tab = (dev_tab_t *)alloc(size, EfiLoaderData);
244 if (dev_tab == NULL) {
245 ERR_PRT((L"failed to allocate handle table"));
246 return EFI_OUT_OF_RESOURCES;
249 status = BS->LocateHandle(ByProtocol, &FileSystemProtocol, NULL, &size, (VOID **)dev_tab);
250 if (status != EFI_SUCCESS) {
251 ERR_PRT((L"failed to get handles: %r", status));
255 ndev = size / sizeof(EFI_HANDLE);
257 for(i=0; i < ndev; i++) {
259 localfs_install_one(dev_tab[i].dev, &intf);
260 /* override device handle with interface pointer */
261 dev_tab[i].intf = intf;
268 localfs_uninstall(VOID)
271 localfs_priv_state_t *lfs;
275 for(i=0; i < ndev; i++) {
276 if (dev_tab[i].intf == NULL) continue;
277 lfs = FS_PRIVATE(dev_tab[i].intf);
278 status = BS->UninstallProtocolInterface(lfs->dev, &LocalFsProtocol, dev_tab[i].intf);
279 if (EFI_ERROR(status)) {
280 ERR_PRT((L"Uninstall %s error: %r", FS_NAME, status));
284 { EFI_DEVICE_PATH *dp; CHAR16 *str;
285 dp = DevicePathFromHandle(lfs->dev);
286 str = DevicePathToStr(dp);
287 Print(L"uninstalled %s on %s\n", FS_NAME, str);
290 free(dev_tab[i].intf);
292 if (dev_tab) free(dev_tab);