Date: Thu, 26 Oct 2006 22:00:04 GMT From: Marcel Moolenaar <marcel@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 108530 for review Message-ID: <200610262200.k9QM04J8038674@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=108530 Change 108530 by marcel@marcel_cluster on 2006/10/26 21:59:56 Eliminate efiboot.h and use the generic devdesc for the EFI file system implementation. Affected files ... .. //depot/projects/ia64/sys/boot/efi/include/efilib.h#6 edit .. //depot/projects/ia64/sys/boot/efi/libefi/efiboot.h#7 delete .. //depot/projects/ia64/sys/boot/efi/libefi/efifs.c#7 edit .. //depot/projects/ia64/sys/boot/efi/libefi/time.c#4 edit Differences ... ==== //depot/projects/ia64/sys/boot/efi/include/efilib.h#6 (text+ko) ==== @@ -26,14 +26,21 @@ * $FreeBSD: src/sys/boot/efi/include/efilib.h,v 1.4 2004/11/28 00:30:22 marcel Exp $ */ +#include <stand.h> + extern EFI_HANDLE IH; extern EFI_SYSTEM_TABLE *ST; extern EFI_BOOT_SERVICES *BS; extern EFI_RUNTIME_SERVICES *RS; +extern struct devsw efifs_dev; +extern struct fs_ops efifs_fsops; + void *efi_get_table(EFI_GUID *tbl); void efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table); +time_t efi_time(EFI_TIME *); + EFI_PHYSICAL_ADDRESS efimd_va2pa(EFI_VIRTUAL_ADDRESS); EFI_STATUS main(int argc, CHAR16 *argv[]); ==== //depot/projects/ia64/sys/boot/efi/libefi/efifs.c#7 (text+ko) ==== @@ -1,5 +1,6 @@ /*- * Copyright (c) 2001 Doug Rabson + * Copyright (c) 2006 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,81 +30,116 @@ #include <sys/param.h> #include <sys/time.h> #include <stddef.h> -#include <stand.h> #include <stdarg.h> +#include <bootstrap.h> + #include <efi.h> #include <efilib.h> -#include "efiboot.h" +#include <efiprot.h> /* Perform I/O in blocks of size EFI_BLOCK_SIZE. */ #define EFI_BLOCK_SIZE (1024 * 1024) +union fileinfo { + EFI_FILE_INFO info; + char bytes[sizeof(EFI_FILE_INFO) + 510]; +}; + +static EFI_GUID sfs_guid = SIMPLE_FILE_SYSTEM_PROTOCOL; +static EFI_GUID fs_guid = EFI_FILE_SYSTEM_INFO_ID; +static EFI_GUID fi_guid = EFI_FILE_INFO_ID; + +static EFI_HANDLE *fs_handles; +static int fs_handle_count; + static int +status_to_errno(EFI_STATUS status) +{ + + switch (status) { + case EFI_ACCESS_DENIED: return (EPERM); + case EFI_BUFFER_TOO_SMALL: return (EOVERFLOW); + case EFI_DEVICE_ERROR: return (EIO); + case EFI_INVALID_PARAMETER: return (EINVAL); + case EFI_MEDIA_CHANGED: return (ESTALE); + case EFI_NO_MEDIA: return (ENXIO); + case EFI_NOT_FOUND: return (ENOENT); + case EFI_OUT_OF_RESOURCES: return (ENOMEM); + case EFI_UNSUPPORTED: return (ENODEV); + case EFI_VOLUME_CORRUPTED: return (EIO); + case EFI_VOLUME_FULL: return (ENOSPC); + case EFI_WRITE_PROTECTED: return (EACCES); + } + return (EDOOFUS); +} + +static int efifs_open(const char *upath, struct open_file *f) { - struct efi_devdesc *dev = f->f_devdata; - static EFI_GUID sfsid = SIMPLE_FILE_SYSTEM_PROTOCOL; - EFI_FILE_IO_INTERFACE *sfs; - EFI_FILE *root; - EFI_FILE *file; + struct devdesc *dev = f->f_devdata; + EFI_FILE_IO_INTERFACE *fsif; + EFI_FILE *file, *root; EFI_STATUS status; - CHAR16 *cp; - CHAR16 *path; + CHAR16 *cp, *path; + + if (f->f_dev != &efifs_dev || dev->d_unit < 0 || + dev->d_unit >= fs_handle_count) + return (EINVAL); - /* - * We cannot blindly assume that f->f_devdata points to a - * efi_devdesc structure. Before we dereference 'dev', make - * sure that the underlying device is ours. - */ - if (f->f_dev != &efifs_dev || dev->d_handle == NULL) - return ENOENT; + if (f->f_fsdata != NULL) + return (EBUSY); - status = BS->HandleProtocol(dev->d_handle, &sfsid, (VOID **)&sfs); + status = BS->HandleProtocol(fs_handles[dev->d_unit], &sfs_guid, + (VOID **)&fsif); if (EFI_ERROR(status)) - return ENOENT; + return (status_to_errno(status)); - /* - * Find the root directory. - */ - status = sfs->OpenVolume(sfs, &root); + /* Get the root directory. */ + status = fsif->OpenVolume(fsif, &root); + if (EFI_ERROR(status)) + return (status_to_errno(status)); - /* - * Convert path to CHAR16, skipping leading separators. - */ while (*upath == '/') upath++; - if (!*upath) { - /* Opening the root directory, */ + + /* Special case: opening the root directory. */ + if (*upath == '\0') { f->f_fsdata = root; - return 0; + return (0); + } + + path = malloc((strlen(upath) + 1) * sizeof(CHAR16)); + if (path == NULL) { + root->Close(root); + return (ENOMEM); } - cp = path = malloc((strlen(upath) + 1) * sizeof(CHAR16)); - if (path == NULL) - return ENOMEM; - while (*upath) { - if (*upath == '/') + + cp = path; + while (*upath != '\0') { + if (*upath == '/') { *cp = '\\'; - else + if (upath[1] == '/') + upath++; + } else *cp = *upath; upath++; cp++; } - *cp++ = 0; + *cp = 0; - /* - * Try to open it. - */ - status = root->Open(root, &file, path, EFI_FILE_MODE_READ, 0); + /* Open the file. */ + status = root->Open(root, &file, path, + EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, 0); + if (status == EFI_WRITE_PROTECTED) + status = root->Open(root, &file, path, EFI_FILE_MODE_READ, 0); free(path); - if (EFI_ERROR(status)) { - root->Close(root); - return ENOENT; - } + root->Close(root); + if (EFI_ERROR(status)) + return (status_to_errno(status)); - root->Close(root); f->f_fsdata = file; - return 0; + return (0); } static int @@ -111,8 +147,12 @@ { EFI_FILE *file = f->f_fsdata; + if (file == NULL) + return (EBADF); + file->Close(file); - return 0; + f->f_fsdata = NULL; + return (0); } static int @@ -123,6 +163,9 @@ UINTN sz = size; char *bufp; + if (file == NULL) + return (EBADF); + bufp = buf; while (size > 0) { sz = size; @@ -131,7 +174,7 @@ status = file->Read(file, &sz, bufp); twiddle(); if (EFI_ERROR(status)) - return EIO; + return (status_to_errno(status)); if (sz == 0) break; size -= sz; @@ -139,7 +182,7 @@ } if (resid) *resid = size; - return 0; + return (0); } static int @@ -150,6 +193,9 @@ UINTN sz = size; char *bufp; + if (file == NULL) + return (EBADF); + bufp = buf; while (size > 0) { sz = size; @@ -158,7 +204,7 @@ status = file->Write(file, &sz, bufp); twiddle(); if (EFI_ERROR(status)) - return EIO; + return (status_to_errno(status)); if (sz == 0) break; size -= sz; @@ -166,7 +212,7 @@ } if (resid) *resid = size; - return 0; + return (0); } static off_t @@ -175,128 +221,118 @@ EFI_FILE *file = f->f_fsdata; EFI_STATUS status; UINT64 base; - UINTN sz; - static EFI_GUID infoid = EFI_FILE_INFO_ID; - EFI_FILE_INFO info; + + if (file == NULL) + return (EBADF); switch (where) { case SEEK_SET: - base = 0; break; + case SEEK_END: + status = file->SetPosition(file, ~0ULL); + if (EFI_ERROR(status)) + return (-1); + /* FALLTHROUGH */ + case SEEK_CUR: status = file->GetPosition(file, &base); if (EFI_ERROR(status)) - return -1; + return (-1); + offset = (off_t)(base + offset); break; - case SEEK_END: - sz = sizeof(info); - status = file->GetInfo(file, &infoid, &sz, &info); - if (EFI_ERROR(status)) - return -1; - base = info.FileSize; - break; + default: + return (-1); } + if (offset < 0) + return (-1); - status = file->SetPosition(file, base + offset); - if (EFI_ERROR(status)) - return -1; - file->GetPosition(file, &base); - - return base; + status = file->SetPosition(file, (UINT64)offset); + return (EFI_ERROR(status) ? -1 : offset); } static int efifs_stat(struct open_file *f, struct stat *sb) { EFI_FILE *file = f->f_fsdata; + union fileinfo fi; EFI_STATUS status; - char *buf; UINTN sz; - static EFI_GUID infoid = EFI_FILE_INFO_ID; - EFI_FILE_INFO *info; + + if (file == NULL) + return (EBADF); bzero(sb, sizeof(*sb)); - buf = malloc(1024); - sz = 1024; + sz = sizeof(fi); + status = file->GetInfo(file, &fi_guid, &sz, &fi); + if (EFI_ERROR(status)) + return (status_to_errno(status)); - status = file->GetInfo(file, &infoid, &sz, buf); - if (EFI_ERROR(status)) { - free(buf); - return -1; - } - - info = (EFI_FILE_INFO *) buf; - - if (info->Attribute & EFI_FILE_READ_ONLY) - sb->st_mode = S_IRUSR; - else - sb->st_mode = S_IRUSR | S_IWUSR; - if (info->Attribute & EFI_FILE_DIRECTORY) + sb->st_mode = S_IRUSR | S_IRGRP | S_IROTH; + if ((fi.info.Attribute & EFI_FILE_READ_ONLY) == 0) + sb->st_mode |= S_IWUSR | S_IWGRP | S_IWOTH; + if (fi.info.Attribute & EFI_FILE_DIRECTORY) sb->st_mode |= S_IFDIR; else sb->st_mode |= S_IFREG; - sb->st_size = info->FileSize; - - free(buf); - return 0; + sb->st_nlink = 1; + sb->st_atime = efi_time(&fi.info.LastAccessTime); + sb->st_mtime = efi_time(&fi.info.ModificationTime); + sb->st_ctime = efi_time(&fi.info.CreateTime); + sb->st_size = fi.info.FileSize; + sb->st_blocks = fi.info.PhysicalSize / S_BLKSIZE; + sb->st_blksize = S_BLKSIZE; + sb->st_birthtime = sb->st_ctime; + return (0); } static int efifs_readdir(struct open_file *f, struct dirent *d) { EFI_FILE *file = f->f_fsdata; + union fileinfo fi; EFI_STATUS status; - char *buf; UINTN sz; - EFI_FILE_INFO *info; int i; - buf = malloc(1024); - sz = 1024; + if (file == NULL) + return (EBADF); - status = file->Read(file, &sz, buf); - if (EFI_ERROR(status) || sz < offsetof(EFI_FILE_INFO, FileName)) - return ENOENT; - - info = (EFI_FILE_INFO *) buf; + sz = sizeof(fi); + status = file->Read(file, &sz, &fi); + if (EFI_ERROR(status)) + return (status_to_errno(status)); d->d_fileno = 0; d->d_reclen = sizeof(*d); - if (info->Attribute & EFI_FILE_DIRECTORY) + if (fi.info.Attribute & EFI_FILE_DIRECTORY) d->d_type = DT_DIR; else d->d_type = DT_REG; - d->d_namlen = ((info->Size - offsetof(EFI_FILE_INFO, FileName)) - / sizeof(CHAR16)); + d->d_namlen = (fi.info.Size - sizeof(EFI_FILE_INFO)) / sizeof(CHAR16); for (i = 0; i < d->d_namlen; i++) - d->d_name[i] = info->FileName[i]; + d->d_name[i] = fi.info.FileName[i]; d->d_name[i] = 0; - - free(buf); - return 0; + return (0); } -struct fs_ops efi_fsops = { - "fs", - efifs_open, - efifs_close, - efifs_read, - efifs_write, - efifs_seek, - efifs_stat, - efifs_readdir +struct fs_ops efifs_fsops = { + .fs_name = "fs", + .fo_open = efifs_open, + .fo_close = efifs_close, + .fo_read = efifs_read, + .fo_write = efifs_write, + .fo_seek = efifs_seek, + .fo_stat = efifs_stat, + .fo_readdir = efifs_readdir }; -static EFI_HANDLE *fs_handles; -UINTN fs_handle_count; - int efifs_get_unit(EFI_HANDLE h) { - UINTN u; + int u; u = 0; while (u < fs_handle_count && fs_handles[u] != h) @@ -309,22 +345,22 @@ { EFI_STATUS status; UINTN sz; - static EFI_GUID sfsid = SIMPLE_FILE_SYSTEM_PROTOCOL; sz = 0; - status = BS->LocateHandle(ByProtocol, &sfsid, 0, &sz, 0); - if (status != EFI_BUFFER_TOO_SMALL) - return ENOENT; - fs_handles = (EFI_HANDLE *) malloc(sz); - status = BS->LocateHandle(ByProtocol, &sfsid, 0, - &sz, fs_handles); - if (EFI_ERROR(status)) { - free(fs_handles); - return ENOENT; + status = BS->LocateHandle(ByProtocol, &sfs_guid, 0, &sz, 0); + if (status == EFI_BUFFER_TOO_SMALL) { + fs_handles = (EFI_HANDLE *)malloc(sz); + status = BS->LocateHandle(ByProtocol, &sfs_guid, 0, &sz, + fs_handles); + if (EFI_ERROR(status)) { + free(fs_handles); + fs_handles = NULL; + } } + if (EFI_ERROR(status)) + return (status_to_errno(status)); fs_handle_count = sz / sizeof(EFI_HANDLE); - - return 0; + return (0); } /* @@ -333,14 +369,53 @@ static void efifs_dev_print(int verbose) { - int i; - char line[80]; + union { + EFI_FILE_SYSTEM_INFO info; + char buffer[1024]; + } fi; + char line[80]; + EFI_FILE_IO_INTERFACE *fsif; + EFI_FILE *volume; + EFI_STATUS status; + UINTN sz; + int h, i; - for (i = 0; i < fs_handle_count; i++) { - sprintf(line, " fs%d: EFI filesystem", i); + for (h = 0; h < fs_handle_count; h++) { + sprintf(line, " fs%d: ", h); pager_output(line); - /* XXX more detail? */ + + status = BS->HandleProtocol(fs_handles[h], &sfs_guid, + (VOID **)&fsif); + if (EFI_ERROR(status)) + goto err; + + status = fsif->OpenVolume(fsif, &volume); + if (EFI_ERROR(status)) + goto err; + + status = volume->GetInfo(volume, &fs_guid, &sz, &fi); + volume->Close(volume); + if (EFI_ERROR(status)) + goto err; + + if (fi.info.ReadOnly) + pager_output("[RO] "); + else + pager_output(" "); + for (i = 0; fi.info.VolumeLabel[i] != 0; i++) + fi.buffer[i] = fi.info.VolumeLabel[i]; + fi.buffer[i] = 0; + if (fi.buffer[0] != 0) + pager_output(fi.buffer); + else + pager_output("EFI filesystem"); pager_output("\n"); + continue; + + err: + sprintf(line, "[--] error obtaining information: status %ld\n", + status); + pager_output(line); } } @@ -357,45 +432,40 @@ static int efifs_dev_open(struct open_file *f, ...) { - va_list args; - struct efi_devdesc *dev; - int unit; + va_list args; + struct devdesc *dev; va_start(args, f); - dev = va_arg(args, struct efi_devdesc*); + dev = va_arg(args, struct devdesc*); va_end(args); - unit = dev->d_kind.efidisk.unit; - if (unit < 0 || unit >= fs_handle_count) { - printf("attempt to open nonexistent EFI filesystem\n"); + if (dev->d_unit < 0 || dev->d_unit >= fs_handle_count) return(ENXIO); - } - - dev->d_handle = fs_handles[unit]; - - return 0; + return (0); } static int efifs_dev_close(struct open_file *f) { - return 0; + return (0); } static int efifs_dev_strategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf, size_t *rsize) { - return 0; + + return (0); } struct devsw efifs_dev = { - "fs", - DEVT_DISK, - efifs_dev_init, - efifs_dev_strategy, - efifs_dev_open, - efifs_dev_close, - noioctl, - efifs_dev_print + .dv_name = "fs", + .dv_type = DEVT_DISK, + .dv_init = efifs_dev_init, + .dv_strategy = efifs_dev_strategy, + .dv_open = efifs_dev_open, + .dv_close = efifs_dev_close, + .dv_ioctl = noioctl, + .dv_print = efifs_dev_print, + .dv_cleanup = NULL }; ==== //depot/projects/ia64/sys/boot/efi/libefi/time.c#4 (text+ko) ==== @@ -59,7 +59,7 @@ #define SECSPERDAY (24 * SECSPERHOUR) time_t -EfiTimeToUnixTime(EFI_TIME *ETime) +efi_time(EFI_TIME *ETime) { /* // These arrays give the cumulative number of days up to the first of the @@ -170,15 +170,15 @@ OUT struct timezone *tzp ) { - EFI_TIME EfiTime; + EFI_TIME EfiTime; EFI_TIME_CAPABILITIES Capabilities; - EFI_STATUS Status; + EFI_STATUS Status; /* // Get time from EFI */ - Status = RS->GetTime( &EfiTime, &Capabilities ); + Status = RS->GetTime(&EfiTime, &Capabilities); if (EFI_ERROR(Status)) return (-1); @@ -186,7 +186,7 @@ // Convert to UNIX time (ie seconds since the epoch */ - tp->tv_sec = EfiTimeToUnixTime( &EfiTime ); + tp->tv_sec = efi_time( &EfiTime ); tp->tv_usec = 0; /* EfiTime.Nanosecond * 1000; */ /*
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200610262200.k9QM04J8038674>