? :wq ? obj Index: conf.c =================================================================== RCS file: /cvs/src/sys/arch/arm64/stand/efiboot/conf.c,v retrieving revision 1.44 diff -u -p -r1.44 conf.c --- conf.c 15 Feb 2023 14:13:38 -0000 1.44 +++ conf.c 15 Apr 2023 01:26:57 -0000 @@ -58,6 +58,8 @@ struct fs_ops file_system[] = { ufs_stat, ufs_readdir, ufs_fchmod }, { ufs2_open, ufs2_close, ufs2_read, ufs2_write, ufs2_seek, ufs2_stat, ufs2_readdir, ufs2_fchmod }, + { esp_open, esp_close, esp_read, esp_write, esp_seek, + esp_stat, esp_readdir, } }; int nfsys = nitems(file_system); Index: efidev.c =================================================================== RCS file: /cvs/src/sys/arch/arm64/stand/efiboot/efidev.c,v retrieving revision 1.11 diff -u -p -r1.11 efidev.c --- efidev.c 1 Sep 2022 13:45:26 -0000 1.11 +++ efidev.c 15 Apr 2023 01:26:57 -0000 @@ -565,3 +565,181 @@ efiioctl(struct open_file *f, u_long cmd { return 0; } + +/* + * load a file from the EFI System Partition + */ +static EFI_GUID lip_guid = LOADED_IMAGE_PROTOCOL; +static EFI_GUID sfsp_guid = SIMPLE_FILE_SYSTEM_PROTOCOL; +static EFI_GUID fi_guid = EFI_FILE_INFO_ID; + +int +esp_open(char *path, struct open_file *f) +{ + extern EFI_HANDLE IH; + extern EFI_BOOT_SERVICES *BS; + + EFI_LOADED_IMAGE *li = NULL; + EFI_FILE_IO_INTERFACE *ESPVolume; + CHAR16 *fname; + EFI_FILE_HANDLE VH, FH; + UINTN pathlen, i; + EFI_STATUS status; + + if (strcmp("esp", f->f_dev->dv_name) != 0) + return ENXIO; + + if (IH == NULL) + return ENXIO; + + /* get the loaded image protocol interface */ + status = BS->HandleProtocol(IH, &lip_guid, (void **)&li); + if (status != EFI_SUCCESS) + return ENXIO; + + /* get a fs handle */ + status = BS->HandleProtocol(li->DeviceHandle, &sfsp_guid, + (void *)&ESPVolume); + if (status != EFI_SUCCESS) + return ENXIO; + + status = ESPVolume->OpenVolume(ESPVolume, &VH); + if (status != EFI_SUCCESS) + return ENXIO; + + pathlen = strlen(path) + 1; + fname = alloc(pathlen * sizeof(*fname)); + if (fname == NULL) + return ENOMEM; + +#if 0 + status = AsciiStrToUnicodeStrS(path, fname, pathlen); + if (status != EFI_SUCCESS) + goto free; +#endif + for (i = 0; i < pathlen; i++) + fname[i] = path[i]; + + status = VH->Open(VH, &FH, fname, EFI_FILE_MODE_READ, + EFI_FILE_READ_ONLY /*| EFI_FILE_HIDDEN*/ | EFI_FILE_SYSTEM); + free(fname, pathlen * sizeof(*fname)); + if (status != EFI_SUCCESS) + return (EIO); + + f->f_fsdata = FH; + return (0); +} + +int +esp_close(struct open_file *f) +{ + EFI_FILE_HANDLE FH = f->f_fsdata; + FH->Close(FH); + return 0; +} + +int +esp_read(struct open_file *f, void *addr, size_t size, size_t *resid) +{ + EFI_FILE_HANDLE FH = f->f_fsdata; + UINT64 readlen = size; + EFI_STATUS status; + + status = FH->Read(FH, &readlen, addr); + if (status != EFI_SUCCESS) + return (EIO); + + *resid = readlen; + return (0); +} + +int +esp_write(struct open_file *f, void *start, size_t size, size_t *resid) +{ + return (EROFS); +} + +off_t +esp_seek(struct open_file *f, off_t offset, int where) +{ + EFI_FILE_HANDLE FH = f->f_fsdata; + UINT64 position; + EFI_STATUS status; + + switch(where) { + case SEEK_CUR: + status = FH->GetPosition(FH, &position); + if (status != EFI_SUCCESS) { + errno = EIO; + return ((off_t)-1); + } + + position += where; + break; + case SEEK_SET: + position = where; + break; + case SEEK_END: + position = 0xFFFFFFFFFFFFFFFF; + break; + default: + errno = EINVAL; + return ((off_t)-1); + } + + status = FH->SetPosition(FH, position); + if (status != EFI_SUCCESS) { + errno = EIO; + return ((off_t)-1); + } + + return (0); +} + +int +esp_stat(struct open_file *f, struct stat *sb) +{ + + EFI_FILE_HANDLE FH = f->f_fsdata; + EFI_FILE_INFO fi; + EFI_FILE_INFO *fip = &fi; + UINTN filen = sizeof(fi); + EFI_STATUS status; + ssize_t rv = -1; + + sb->st_mode = 0444; + sb->st_nlink = 1; + sb->st_uid = 0; + sb->st_gid = 0; + + status = FH->GetInfo(FH, &fi_guid, &filen, fip); + switch (status) { + case EFI_SUCCESS: + sb->st_size = fip->FileSize; + return (0); + case EFI_BUFFER_TOO_SMALL: + break; + default: + return (EIO); + } + + fip = alloc(filen); + if (fip == NULL) + return (ENOMEM); + + status = FH->GetInfo(FH, &fi_guid, &filen, fip); + if (status != EFI_SUCCESS) + goto done; + + sb->st_size = fip->FileSize; + +done: + free(fip, filen); + return (rv); +} + +int +esp_readdir(struct open_file *f, char *name) +{ + return EOPNOTSUPP; +} Index: efidev.h =================================================================== RCS file: /cvs/src/sys/arch/arm64/stand/efiboot/efidev.h,v retrieving revision 1.3 diff -u -p -r1.3 efidev.h --- efidev.h 9 Dec 2020 18:10:18 -0000 1.3 +++ efidev.h 15 Apr 2023 01:26:57 -0000 @@ -34,3 +34,11 @@ int efiopen(struct open_file *, ...); int efistrategy(void *, int, daddr_t, size_t, void *, size_t *); int eficlose(struct open_file *); int efiioctl(struct open_file *, u_long, void *); + +int esp_open(char *, struct open_file *); +int esp_close(struct open_file *); +int esp_read(struct open_file *, void *, size_t, size_t *); +int esp_write(struct open_file *, void *, size_t, size_t *); +off_t esp_seek(struct open_file *, off_t, int); +int esp_stat(struct open_file *, struct stat *); +int esp_readdir(struct open_file *, char *);