Index: head/sbin/fsck_msdosfs/boot.c =================================================================== --- head/sbin/fsck_msdosfs/boot.c (revision 273864) +++ head/sbin/fsck_msdosfs/boot.c (revision 273865) @@ -1,275 +1,275 @@ /* * Copyright (C) 1995, 1997 Wolfgang Solfrank * Copyright (c) 1995 Martin Husemann * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #ifndef lint __RCSID("$NetBSD: boot.c,v 1.11 2006/06/05 16:51:18 christos Exp "); static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ #include #include #include #include #include "ext.h" #include "fsutil.h" int readboot(int dosfs, struct bootblock *boot) { u_char block[DOSBOOTBLOCKSIZE]; u_char fsinfo[2 * DOSBOOTBLOCKSIZE]; u_char backup[DOSBOOTBLOCKSIZE]; int ret = FSOK; int i; if ((size_t)read(dosfs, block, sizeof block) != sizeof block) { perr("could not read boot block"); return FSFATAL; } if (block[510] != 0x55 || block[511] != 0xaa) { pfatal("Invalid signature in boot block: %02x%02x", block[511], block[510]); return FSFATAL; } memset(boot, 0, sizeof *boot); boot->ValidFat = -1; /* decode bios parameter block */ boot->bpbBytesPerSec = block[11] + (block[12] << 8); boot->bpbSecPerClust = block[13]; boot->bpbResSectors = block[14] + (block[15] << 8); boot->bpbFATs = block[16]; boot->bpbRootDirEnts = block[17] + (block[18] << 8); boot->bpbSectors = block[19] + (block[20] << 8); boot->bpbMedia = block[21]; boot->bpbFATsmall = block[22] + (block[23] << 8); boot->SecPerTrack = block[24] + (block[25] << 8); boot->bpbHeads = block[26] + (block[27] << 8); boot->bpbHiddenSecs = block[28] + (block[29] << 8) + (block[30] << 16) + (block[31] << 24); boot->bpbHugeSectors = block[32] + (block[33] << 8) + (block[34] << 16) + (block[35] << 24); boot->FATsecs = boot->bpbFATsmall; if (!boot->bpbRootDirEnts) boot->flags |= FAT32; if (boot->flags & FAT32) { boot->FATsecs = block[36] + (block[37] << 8) + (block[38] << 16) + (block[39] << 24); if (block[40] & 0x80) boot->ValidFat = block[40] & 0x0f; /* check version number: */ if (block[42] || block[43]) { /* Correct? XXX */ pfatal("Unknown file system version: %x.%x", block[43], block[42]); return FSFATAL; } boot->bpbRootClust = block[44] + (block[45] << 8) + (block[46] << 16) + (block[47] << 24); boot->bpbFSInfo = block[48] + (block[49] << 8); boot->bpbBackup = block[50] + (block[51] << 8); if (lseek(dosfs, boot->bpbFSInfo * boot->bpbBytesPerSec, SEEK_SET) != boot->bpbFSInfo * boot->bpbBytesPerSec || read(dosfs, fsinfo, sizeof fsinfo) != sizeof fsinfo) { perr("could not read fsinfo block"); return FSFATAL; } if (memcmp(fsinfo, "RRaA", 4) || memcmp(fsinfo + 0x1e4, "rrAa", 4) || fsinfo[0x1fc] || fsinfo[0x1fd] || fsinfo[0x1fe] != 0x55 || fsinfo[0x1ff] != 0xaa || fsinfo[0x3fc] || fsinfo[0x3fd] || fsinfo[0x3fe] != 0x55 || fsinfo[0x3ff] != 0xaa) { pwarn("Invalid signature in fsinfo block\n"); if (ask(0, "Fix")) { memcpy(fsinfo, "RRaA", 4); memcpy(fsinfo + 0x1e4, "rrAa", 4); fsinfo[0x1fc] = fsinfo[0x1fd] = 0; fsinfo[0x1fe] = 0x55; fsinfo[0x1ff] = 0xaa; fsinfo[0x3fc] = fsinfo[0x3fd] = 0; fsinfo[0x3fe] = 0x55; fsinfo[0x3ff] = 0xaa; if (lseek(dosfs, boot->bpbFSInfo * boot->bpbBytesPerSec, SEEK_SET) != boot->bpbFSInfo * boot->bpbBytesPerSec || write(dosfs, fsinfo, sizeof fsinfo) != sizeof fsinfo) { perr("Unable to write bpbFSInfo"); return FSFATAL; } ret = FSBOOTMOD; } else boot->bpbFSInfo = 0; } if (boot->bpbFSInfo) { boot->FSFree = fsinfo[0x1e8] + (fsinfo[0x1e9] << 8) + (fsinfo[0x1ea] << 16) + (fsinfo[0x1eb] << 24); boot->FSNext = fsinfo[0x1ec] + (fsinfo[0x1ed] << 8) + (fsinfo[0x1ee] << 16) + (fsinfo[0x1ef] << 24); } if (lseek(dosfs, boot->bpbBackup * boot->bpbBytesPerSec, SEEK_SET) != boot->bpbBackup * boot->bpbBytesPerSec || read(dosfs, backup, sizeof backup) != sizeof backup) { perr("could not read backup bootblock"); return FSFATAL; } backup[65] = block[65]; /* XXX */ if (memcmp(block + 11, backup + 11, 79)) { /* * XXX We require a reference that explains * that these bytes need to match, or should * drop the check. gdt@NetBSD has observed * filesystems that work fine under Windows XP * and NetBSD that do not match, so the * requirement is suspect. For now, just * print out useful information and continue. */ pfatal("backup (block %d) mismatch with primary bootblock:\n", boot->bpbBackup); for (i = 11; i < 11 + 90; i++) { if (block[i] != backup[i]) pfatal("\ti=%d\tprimary 0x%02x\tbackup 0x%02x\n", i, block[i], backup[i]); } } /* Check backup bpbFSInfo? XXX */ } boot->ClusterOffset = (boot->bpbRootDirEnts * 32 + boot->bpbBytesPerSec - 1) / boot->bpbBytesPerSec + boot->bpbResSectors + boot->bpbFATs * boot->FATsecs - CLUST_FIRST * boot->bpbSecPerClust; - if (boot->bpbBytesPerSec % DOSBOOTBLOCKSIZE != 0) { + if (boot->bpbBytesPerSec % DOSBOOTBLOCKSIZE_REAL != 0) { pfatal("Invalid sector size: %u", boot->bpbBytesPerSec); return FSFATAL; } if (boot->bpbSecPerClust == 0) { pfatal("Invalid cluster size: %u", boot->bpbSecPerClust); return FSFATAL; } if (boot->bpbSectors) { boot->bpbHugeSectors = 0; boot->NumSectors = boot->bpbSectors; } else boot->NumSectors = boot->bpbHugeSectors; boot->NumClusters = (boot->NumSectors - boot->ClusterOffset) / boot->bpbSecPerClust; if (boot->flags&FAT32) boot->ClustMask = CLUST32_MASK; else if (boot->NumClusters < (CLUST_RSRVD&CLUST12_MASK)) boot->ClustMask = CLUST12_MASK; else if (boot->NumClusters < (CLUST_RSRVD&CLUST16_MASK)) boot->ClustMask = CLUST16_MASK; else { pfatal("Filesystem too big (%u clusters) for non-FAT32 partition", boot->NumClusters); return FSFATAL; } switch (boot->ClustMask) { case CLUST32_MASK: boot->NumFatEntries = (boot->FATsecs * boot->bpbBytesPerSec) / 4; break; case CLUST16_MASK: boot->NumFatEntries = (boot->FATsecs * boot->bpbBytesPerSec) / 2; break; default: boot->NumFatEntries = (boot->FATsecs * boot->bpbBytesPerSec * 2) / 3; break; } if (boot->NumFatEntries < boot->NumClusters) { pfatal("FAT size too small, %u entries won't fit into %u sectors\n", boot->NumClusters, boot->FATsecs); return FSFATAL; } boot->ClusterSize = boot->bpbBytesPerSec * boot->bpbSecPerClust; boot->NumFiles = 1; boot->NumFree = 0; return ret; } int writefsinfo(int dosfs, struct bootblock *boot) { u_char fsinfo[2 * DOSBOOTBLOCKSIZE]; if (lseek(dosfs, boot->bpbFSInfo * boot->bpbBytesPerSec, SEEK_SET) != boot->bpbFSInfo * boot->bpbBytesPerSec || read(dosfs, fsinfo, sizeof fsinfo) != sizeof fsinfo) { perr("could not read fsinfo block"); return FSFATAL; } fsinfo[0x1e8] = (u_char)boot->FSFree; fsinfo[0x1e9] = (u_char)(boot->FSFree >> 8); fsinfo[0x1ea] = (u_char)(boot->FSFree >> 16); fsinfo[0x1eb] = (u_char)(boot->FSFree >> 24); fsinfo[0x1ec] = (u_char)boot->FSNext; fsinfo[0x1ed] = (u_char)(boot->FSNext >> 8); fsinfo[0x1ee] = (u_char)(boot->FSNext >> 16); fsinfo[0x1ef] = (u_char)(boot->FSNext >> 24); if (lseek(dosfs, boot->bpbFSInfo * boot->bpbBytesPerSec, SEEK_SET) != boot->bpbFSInfo * boot->bpbBytesPerSec || write(dosfs, fsinfo, sizeof fsinfo) != sizeof fsinfo) { perr("Unable to write bpbFSInfo"); return FSFATAL; } /* * Technically, we should return FSBOOTMOD here. * * However, since Win95 OSR2 (the first M$ OS that has * support for FAT32) doesn't maintain the FSINFO block * correctly, it has to be fixed pretty often. * * Therefor, we handle the FSINFO block only informally, * fixing it if necessary, but otherwise ignoring the * fact that it was incorrect. */ return 0; } Index: head/sbin/fsck_msdosfs/dosfs.h =================================================================== --- head/sbin/fsck_msdosfs/dosfs.h (revision 273864) +++ head/sbin/fsck_msdosfs/dosfs.h (revision 273865) @@ -1,137 +1,139 @@ /* * Copyright (C) 1995, 1996, 1997 Wolfgang Solfrank * Copyright (c) 1995 Martin Husemann * Some structure declaration borrowed from Paul Popelka * (paulp@uts.amdahl.com), see /sys/msdosfs/ for reference. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * $NetBSD: dosfs.h,v 1.4 1997/01/03 14:32:48 ws Exp $ * $FreeBSD$ */ #ifndef DOSFS_H #define DOSFS_H -#define DOSBOOTBLOCKSIZE 512 +/* support 4Kn disk reads */ +#define DOSBOOTBLOCKSIZE_REAL 512 +#define DOSBOOTBLOCKSIZE 4096 typedef u_int32_t cl_t; /* type holding a cluster number */ /* * architecture independent description of all the info stored in a * FAT boot block. */ struct bootblock { u_int bpbBytesPerSec; /* bytes per sector */ u_int bpbSecPerClust; /* sectors per cluster */ u_int bpbResSectors; /* number of reserved sectors */ u_int bpbFATs; /* number of bpbFATs */ u_int bpbRootDirEnts; /* number of root directory entries */ u_int32_t bpbSectors; /* total number of sectors */ u_int bpbMedia; /* media descriptor */ u_int bpbFATsmall; /* number of sectors per FAT */ u_int SecPerTrack; /* sectors per track */ u_int bpbHeads; /* number of heads */ u_int32_t bpbHiddenSecs; /* # of hidden sectors */ u_int32_t bpbHugeSectors; /* # of sectors if bpbbpbSectors == 0 */ cl_t bpbRootClust; /* Start of Root Directory */ u_int bpbFSInfo; /* FSInfo sector */ u_int bpbBackup; /* Backup of Bootblocks */ cl_t FSFree; /* Number of free clusters acc. FSInfo */ cl_t FSNext; /* Next free cluster acc. FSInfo */ /* and some more calculated values */ u_int flags; /* some flags: */ #define FAT32 1 /* this is a FAT32 file system */ /* * Maybe, we should separate out * various parts of FAT32? XXX */ int ValidFat; /* valid fat if FAT32 non-mirrored */ cl_t ClustMask; /* mask for entries in FAT */ cl_t NumClusters; /* # of entries in a FAT */ u_int32_t NumSectors; /* how many sectors are there */ u_int32_t FATsecs; /* how many sectors are in FAT */ u_int32_t NumFatEntries; /* how many entries really are there */ u_int ClusterOffset; /* at what sector would sector 0 start */ u_int ClusterSize; /* Cluster size in bytes */ /* Now some statistics: */ u_int NumFiles; /* # of plain files */ u_int NumFree; /* # of free clusters */ u_int NumBad; /* # of bad clusters */ }; struct fatEntry { cl_t next; /* pointer to next cluster */ cl_t head; /* pointer to start of chain */ u_int32_t length; /* number of clusters on chain */ int flags; /* see below */ }; #define CLUST_FREE 0 /* 0 means cluster is free */ #define CLUST_FIRST 2 /* 2 is the minimum valid cluster number */ #define CLUST_RSRVD 0xfffffff6 /* start of reserved clusters */ #define CLUST_BAD 0xfffffff7 /* a cluster with a defect */ #define CLUST_EOFS 0xfffffff8 /* start of EOF indicators */ #define CLUST_EOF 0xffffffff /* standard value for last cluster */ /* * Masks for cluster values */ #define CLUST12_MASK 0xfff #define CLUST16_MASK 0xffff #define CLUST32_MASK 0xfffffff #define FAT_USED 1 /* This fat chain is used in a file */ #define DOSLONGNAMELEN 256 /* long name maximal length */ #define LRFIRST 0x40 /* first long name record */ #define LRNOMASK 0x1f /* mask to extract long record * sequence number */ /* * Architecture independent description of a directory entry */ struct dosDirEntry { struct dosDirEntry *parent, /* previous tree level */ *next, /* next brother */ *child; /* if this is a directory */ char name[8+1+3+1]; /* alias name first part */ char lname[DOSLONGNAMELEN]; /* real name */ uint flags; /* attributes */ cl_t head; /* cluster no */ u_int32_t size; /* filesize in bytes */ uint fsckflags; /* flags during fsck */ }; /* Flags in fsckflags: */ #define DIREMPTY 1 #define DIREMPWARN 2 /* * TODO-list of unread directories */ struct dirTodoNode { struct dosDirEntry *dir; struct dirTodoNode *next; }; #endif Index: head/sys/boot/amd64/boot1.efi/boot1.c =================================================================== --- head/sys/boot/amd64/boot1.efi/boot1.c (revision 273864) +++ head/sys/boot/amd64/boot1.efi/boot1.c (revision 273865) @@ -1,542 +1,545 @@ /*- * Copyright (c) 1998 Robert Nordier * All rights reserved. * Copyright (c) 2001 Robert Drehmel * All rights reserved. * Copyright (c) 2014 Nathan Whitehorn * All rights reserved. * * Redistribution and use in source and binary forms are freely * permitted provided that the above copyright notice and this * paragraph and the following disclaimer are duplicated in all * such forms. * * This software is provided "AS IS" and without any express or * implied warranties, including, without limitation, the implied * warranties of merchantability and fitness for a particular * purpose. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #define _PATH_LOADER "/boot/loader.efi" #define _PATH_KERNEL "/boot/kernel/kernel" #define BSIZEMAX 16384 typedef int putc_func_t(char c, void *arg); struct sp_data { char *sp_buf; u_int sp_len; u_int sp_size; }; static const char digits[] = "0123456789abcdef"; static void panic(const char *fmt, ...) __dead2; static int printf(const char *fmt, ...); static int putchar(char c, void *arg); static int vprintf(const char *fmt, va_list ap); static int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap); static int __printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap); static int __putc(char c, void *arg); static int __puts(const char *s, putc_func_t *putc, void *arg); static int __sputc(char c, void *arg); static char *__uitoa(char *buf, u_int val, int base); static char *__ultoa(char *buf, u_long val, int base); static int domount(EFI_DEVICE_PATH *device, EFI_BLOCK_IO *blkio, int quiet); static void load(const char *fname); EFI_SYSTEM_TABLE *systab; EFI_HANDLE *image; static void bcopy(const void *src, void *dst, size_t len) { const char *s = src; char *d = dst; while (len-- != 0) *d++ = *s++; } static void memcpy(void *dst, const void *src, size_t len) { bcopy(src, dst, len); } static void bzero(void *b, size_t len) { char *p = b; while (len-- != 0) *p++ = 0; } static int strcmp(const char *s1, const char *s2) { for (; *s1 == *s2 && *s1; s1++, s2++) ; return ((u_char)*s1 - (u_char)*s2); } static EFI_GUID BlockIoProtocolGUID = BLOCK_IO_PROTOCOL; static EFI_GUID DevicePathGUID = DEVICE_PATH_PROTOCOL; static EFI_GUID LoadedImageGUID = LOADED_IMAGE_PROTOCOL; static EFI_GUID ConsoleControlGUID = EFI_CONSOLE_CONTROL_PROTOCOL_GUID; static EFI_BLOCK_IO *bootdev; static EFI_DEVICE_PATH *bootdevpath; static EFI_HANDLE *bootdevhandle; EFI_STATUS efi_main(EFI_HANDLE Ximage, EFI_SYSTEM_TABLE* Xsystab) { EFI_HANDLE handles[128]; EFI_BLOCK_IO *blkio; UINTN i, nparts = sizeof(handles); EFI_STATUS status; EFI_DEVICE_PATH *devpath; EFI_BOOT_SERVICES *BS; EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL; char *path = _PATH_LOADER; systab = Xsystab; image = Ximage; BS = systab->BootServices; status = BS->LocateProtocol(&ConsoleControlGUID, NULL, (VOID **)&ConsoleControl); if (status == EFI_SUCCESS) (void)ConsoleControl->SetMode(ConsoleControl, EfiConsoleControlScreenText); printf(" \n>> FreeBSD EFI boot block\n"); printf(" Loader path: %s\n", path); status = systab->BootServices->LocateHandle(ByProtocol, &BlockIoProtocolGUID, NULL, &nparts, handles); nparts /= sizeof(handles[0]); for (i = 0; i < nparts; i++) { status = systab->BootServices->HandleProtocol(handles[i], &DevicePathGUID, (void **)&devpath); if (EFI_ERROR(status)) continue; while (!IsDevicePathEnd(NextDevicePathNode(devpath))) devpath = NextDevicePathNode(devpath); status = systab->BootServices->HandleProtocol(handles[i], &BlockIoProtocolGUID, (void **)&blkio); if (EFI_ERROR(status)) continue; if (!blkio->Media->LogicalPartition) continue; if (domount(devpath, blkio, 1) >= 0) break; } if (i == nparts) panic("No bootable partition found"); bootdevhandle = handles[i]; load(path); panic("Load failed"); return EFI_SUCCESS; } static int dskread(void *buf, u_int64_t lba, int nblk) { EFI_STATUS status; + int size; + lba = lba / (bootdev->Media->BlockSize / DEV_BSIZE); + size = nblk * DEV_BSIZE; status = bootdev->ReadBlocks(bootdev, bootdev->Media->MediaId, lba, - nblk * bootdev->Media->BlockSize, buf); + size, buf); if (EFI_ERROR(status)) return (-1); return (0); } #include "ufsread.c" static ssize_t fsstat(ufs_ino_t inode) { #ifndef UFS2_ONLY static struct ufs1_dinode dp1; ufs1_daddr_t addr1; #endif #ifndef UFS1_ONLY static struct ufs2_dinode dp2; #endif static struct fs fs; static ufs_ino_t inomap; char *blkbuf; void *indbuf; size_t n, nb, size, off, vboff; ufs_lbn_t lbn; ufs2_daddr_t addr2, vbaddr; static ufs2_daddr_t blkmap, indmap; u_int u; blkbuf = dmadat->blkbuf; indbuf = dmadat->indbuf; if (!dsk_meta) { inomap = 0; for (n = 0; sblock_try[n] != -1; n++) { if (dskread(dmadat->sbbuf, sblock_try[n] / DEV_BSIZE, SBLOCKSIZE / DEV_BSIZE)) return -1; memcpy(&fs, dmadat->sbbuf, sizeof(struct fs)); if (( #if defined(UFS1_ONLY) fs.fs_magic == FS_UFS1_MAGIC #elif defined(UFS2_ONLY) (fs.fs_magic == FS_UFS2_MAGIC && fs.fs_sblockloc == sblock_try[n]) #else fs.fs_magic == FS_UFS1_MAGIC || (fs.fs_magic == FS_UFS2_MAGIC && fs.fs_sblockloc == sblock_try[n]) #endif ) && fs.fs_bsize <= MAXBSIZE && fs.fs_bsize >= sizeof(struct fs)) break; } if (sblock_try[n] == -1) { printf("Not ufs\n"); return -1; } dsk_meta++; } else memcpy(&fs, dmadat->sbbuf, sizeof(struct fs)); if (!inode) return 0; if (inomap != inode) { n = IPERVBLK(&fs); if (dskread(blkbuf, INO_TO_VBA(&fs, n, inode), DBPERVBLK)) return -1; n = INO_TO_VBO(n, inode); #if defined(UFS1_ONLY) memcpy(&dp1, (struct ufs1_dinode *)blkbuf + n, sizeof(struct ufs1_dinode)); #elif defined(UFS2_ONLY) memcpy(&dp2, (struct ufs2_dinode *)blkbuf + n, sizeof(struct ufs2_dinode)); #else if (fs.fs_magic == FS_UFS1_MAGIC) memcpy(&dp1, (struct ufs1_dinode *)blkbuf + n, sizeof(struct ufs1_dinode)); else memcpy(&dp2, (struct ufs2_dinode *)blkbuf + n, sizeof(struct ufs2_dinode)); #endif inomap = inode; fs_off = 0; blkmap = indmap = 0; } size = DIP(di_size); n = size - fs_off; return (n); } static struct dmadat __dmadat; static int domount(EFI_DEVICE_PATH *device, EFI_BLOCK_IO *blkio, int quiet) { dmadat = &__dmadat; bootdev = blkio; bootdevpath = device; if (fsread(0, NULL, 0)) { if (!quiet) printf("domount: can't read superblock\n"); return (-1); } if (!quiet) printf("Succesfully mounted UFS filesystem\n"); return (0); } static void load(const char *fname) { ufs_ino_t ino; EFI_STATUS status; EFI_HANDLE loaderhandle; EFI_LOADED_IMAGE *loaded_image; void *buffer; size_t bufsize; if ((ino = lookup(fname)) == 0) { printf("File %s not found\n", fname); return; } bufsize = fsstat(ino); status = systab->BootServices->AllocatePool(EfiLoaderData, bufsize, &buffer); fsread(ino, buffer, bufsize); /* XXX: For secure boot, we need our own loader here */ status = systab->BootServices->LoadImage(TRUE, image, bootdevpath, buffer, bufsize, &loaderhandle); status = systab->BootServices->HandleProtocol(loaderhandle, &LoadedImageGUID, (VOID**)&loaded_image); loaded_image->DeviceHandle = bootdevhandle; status = systab->BootServices->StartImage(loaderhandle, NULL, NULL); } static void panic(const char *fmt, ...) { char buf[128]; va_list ap; va_start(ap, fmt); vsnprintf(buf, sizeof buf, fmt, ap); printf("panic: %s\n", buf); va_end(ap); while (1) {} } static int printf(const char *fmt, ...) { va_list ap; int ret; /* Don't annoy the user as we probe for partitions */ if (strcmp(fmt,"Not ufs\n") == 0) return 0; va_start(ap, fmt); ret = vprintf(fmt, ap); va_end(ap); return (ret); } static int putchar(char c, void *arg) { CHAR16 buf[2]; if (c == '\n') { buf[0] = '\r'; buf[1] = 0; systab->ConOut->OutputString(systab->ConOut, buf); } buf[0] = c; buf[1] = 0; systab->ConOut->OutputString(systab->ConOut, buf); return (1); } static int vprintf(const char *fmt, va_list ap) { int ret; ret = __printf(fmt, putchar, 0, ap); return (ret); } static int vsnprintf(char *str, size_t sz, const char *fmt, va_list ap) { struct sp_data sp; int ret; sp.sp_buf = str; sp.sp_len = 0; sp.sp_size = sz; ret = __printf(fmt, __sputc, &sp, ap); return (ret); } static int __printf(const char *fmt, putc_func_t *putc, void *arg, va_list ap) { char buf[(sizeof(long) * 8) + 1]; char *nbuf; u_long ul; u_int ui; int lflag; int sflag; char *s; int pad; int ret; int c; nbuf = &buf[sizeof buf - 1]; ret = 0; while ((c = *fmt++) != 0) { if (c != '%') { ret += putc(c, arg); continue; } lflag = 0; sflag = 0; pad = 0; reswitch: c = *fmt++; switch (c) { case '#': sflag = 1; goto reswitch; case '%': ret += putc('%', arg); break; case 'c': c = va_arg(ap, int); ret += putc(c, arg); break; case 'd': if (lflag == 0) { ui = (u_int)va_arg(ap, int); if (ui < (int)ui) { ui = -ui; ret += putc('-', arg); } s = __uitoa(nbuf, ui, 10); } else { ul = (u_long)va_arg(ap, long); if (ul < (long)ul) { ul = -ul; ret += putc('-', arg); } s = __ultoa(nbuf, ul, 10); } ret += __puts(s, putc, arg); break; case 'l': lflag = 1; goto reswitch; case 'o': if (lflag == 0) { ui = (u_int)va_arg(ap, u_int); s = __uitoa(nbuf, ui, 8); } else { ul = (u_long)va_arg(ap, u_long); s = __ultoa(nbuf, ul, 8); } ret += __puts(s, putc, arg); break; case 'p': ul = (u_long)va_arg(ap, void *); s = __ultoa(nbuf, ul, 16); ret += __puts("0x", putc, arg); ret += __puts(s, putc, arg); break; case 's': s = va_arg(ap, char *); ret += __puts(s, putc, arg); break; case 'u': if (lflag == 0) { ui = va_arg(ap, u_int); s = __uitoa(nbuf, ui, 10); } else { ul = va_arg(ap, u_long); s = __ultoa(nbuf, ul, 10); } ret += __puts(s, putc, arg); break; case 'x': if (lflag == 0) { ui = va_arg(ap, u_int); s = __uitoa(nbuf, ui, 16); } else { ul = va_arg(ap, u_long); s = __ultoa(nbuf, ul, 16); } if (sflag) ret += __puts("0x", putc, arg); ret += __puts(s, putc, arg); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': pad = pad * 10 + c - '0'; goto reswitch; default: break; } } return (ret); } static int __sputc(char c, void *arg) { struct sp_data *sp; sp = arg; if (sp->sp_len < sp->sp_size) sp->sp_buf[sp->sp_len++] = c; sp->sp_buf[sp->sp_len] = '\0'; return (1); } static int __puts(const char *s, putc_func_t *putc, void *arg) { const char *p; int ret; ret = 0; for (p = s; *p != '\0'; p++) ret += putc(*p, arg); return (ret); } static char * __uitoa(char *buf, u_int ui, int base) { char *p; p = buf; *p = '\0'; do *--p = digits[ui % base]; while ((ui /= base) != 0); return (p); } static char * __ultoa(char *buf, u_long ul, int base) { char *p; p = buf; *p = '\0'; do *--p = digits[ul % base]; while ((ul /= base) != 0); return (p); }