Index: head/sys/boot/amd64/Makefile =================================================================== --- head/sys/boot/amd64/Makefile (revision 264390) +++ head/sys/boot/amd64/Makefile (revision 264391) @@ -1,7 +1,7 @@ # $FreeBSD$ .include -SUBDIR= efi +SUBDIR= efi boot1.efi .include Index: head/sys/boot/amd64/boot1.efi/Makefile =================================================================== --- head/sys/boot/amd64/boot1.efi/Makefile (nonexistent) +++ head/sys/boot/amd64/boot1.efi/Makefile (revision 264391) @@ -0,0 +1,70 @@ +# $FreeBSD$ + +NO_MAN= + +.include + +# In-tree GCC does not support __attribute__((ms_abi)). +.if ${COMPILER_TYPE} != "gcc" + +MK_SSP= no + +PROG= loader.sym +INTERNALPROG= + +# architecture-specific loader code +SRCS= boot1.c reloc.c start.S + +CFLAGS+= -fPIC +CFLAGS+= -I. +CFLAGS+= -I${.CURDIR}/../../efi/include +CFLAGS+= -I${.CURDIR}/../../efi/include/${MACHINE_CPUARCH} +CFLAGS+= -I${.CURDIR}/../../../contrib/dev/acpica/include +CFLAGS+= -I${.CURDIR}/../../.. + +# Always add MI sources +.PATH: ${.CURDIR}/../../common ../efi +CFLAGS+= -I${.CURDIR}/../../common + +FILES= boot1.efi +FILESMODE_boot1.efi= ${BINMODE} + +LDSCRIPT= ${.CURDIR}/../efi/ldscript.${MACHINE_CPUARCH} +LDFLAGS= -Wl,-T${LDSCRIPT} -Wl,-Bsymbolic -shared -Wl,-znocombreloc + +${PROG}: ${LDSCRIPT} + +OBJCOPY?= objcopy +OBJDUMP?= objdump + +.if ${MACHINE_CPUARCH} == "amd64" +EFI_TARGET= efi-app-x86_64 +.else +EFI_TARGET= efi-app-ia32 +.endif + +boot1.efi: loader.sym + if [ `${OBJDUMP} -t ${.ALLSRC} | fgrep '*UND*' | wc -l` != 0 ]; then \ + ${OBJDUMP} -t ${.ALLSRC} | fgrep '*UND*'; \ + exit 1; \ + fi + ${OBJCOPY} -j .text -j .sdata -j .data \ + -j .dynamic -j .dynsym -j .rel.dyn \ + -j .rela.dyn -j .reloc -j .eh_frame -j set_Xcommand_set \ + --target=${EFI_TARGET} ${.ALLSRC} ${.TARGET} + +CFLAGS+= -I${.CURDIR}/../../common + +.endif # ${COMPILER_TYPE} != "gcc" + +.include + +beforedepend ${OBJS}: machine x86 + +CLEANFILES+= machine x86 + +machine: + ln -sf ${.CURDIR}/../../../amd64/include machine + +x86: + ln -sf ${.CURDIR}/../../../x86/include x86 Property changes on: head/sys/boot/amd64/boot1.efi/Makefile ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/sys/boot/amd64/boot1.efi/boot1.c =================================================================== --- head/sys/boot/amd64/boot1.efi/boot1.c (nonexistent) +++ head/sys/boot/amd64/boot1.efi/boot1.c (revision 264391) @@ -0,0 +1,447 @@ +/*- + * Copyright (c) 1998 Robert Nordier + * All rights reserved. + * Copyright (c) 2001 Robert Drehmel + * 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 + +#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_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; + char *path = _PATH_LOADER; + + systab = Xsystab; + image = Ximage; + + 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; + + status = bootdev->ReadBlocks(bootdev, bootdev->Media->MediaId, lba, + nblk * bootdev->Media->BlockSize, buf); + + if (EFI_ERROR(status)) + return (-1); + + return (0); +} + +#include "ufsread.c" + +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 = fsread(ino, NULL, -1); + 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); +} + Property changes on: head/sys/boot/amd64/boot1.efi/boot1.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/sys/boot/common/ufsread.c =================================================================== --- head/sys/boot/common/ufsread.c (revision 264390) +++ head/sys/boot/common/ufsread.c (revision 264391) @@ -1,304 +1,306 @@ /*- * Copyright (c) 2002 McAfee, Inc. * All rights reserved. * * This software was developed for the FreeBSD Project by Marshall * Kirk McKusick and McAfee Research,, the Security Research Division of * McAfee, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as * part of the DARPA CHATS research program * * 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 AUTHOR AND CONTRIBUTORS ``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 AUTHOR OR CONTRIBUTORS 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. */ /*- * Copyright (c) 1998 Robert Nordier * 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 #ifdef UFS_SMALL_CGBASE /* XXX: Revert to old (broken for over 1.5Tb filesystems) version of cgbase (see sys/ufs/ffs/fs.h rev 1.39) so that small boot loaders (e.g. boot2) can support both UFS1 and UFS2. */ #undef cgbase #define cgbase(fs, c) ((ufs2_daddr_t)((fs)->fs_fpg * (c))) #endif typedef uint32_t ufs_ino_t; /* * We use 4k `virtual' blocks for filesystem data, whatever the actual * filesystem block size. FFS blocks are always a multiple of 4k. */ #define VBLKSHIFT 12 #define VBLKSIZE (1 << VBLKSHIFT) #define VBLKMASK (VBLKSIZE - 1) #define DBPERVBLK (VBLKSIZE / DEV_BSIZE) #define INDIRPERVBLK(fs) (NINDIR(fs) / ((fs)->fs_bsize >> VBLKSHIFT)) #define IPERVBLK(fs) (INOPB(fs) / ((fs)->fs_bsize >> VBLKSHIFT)) #define INO_TO_VBA(fs, ipervblk, x) \ (fsbtodb(fs, cgimin(fs, ino_to_cg(fs, x))) + \ (((x) % (fs)->fs_ipg) / (ipervblk) * DBPERVBLK)) #define INO_TO_VBO(ipervblk, x) ((x) % ipervblk) #define FS_TO_VBA(fs, fsb, off) (fsbtodb(fs, fsb) + \ ((off) / VBLKSIZE) * DBPERVBLK) #define FS_TO_VBO(fs, fsb, off) ((off) & VBLKMASK) /* Buffers that must not span a 64k boundary. */ struct dmadat { char blkbuf[VBLKSIZE]; /* filesystem blocks */ char indbuf[VBLKSIZE]; /* indir blocks */ char sbbuf[SBLOCKSIZE]; /* superblock */ char secbuf[DEV_BSIZE]; /* for MBR/disklabel */ }; static struct dmadat *dmadat; static ufs_ino_t lookup(const char *); static ssize_t fsread(ufs_ino_t, void *, size_t); static uint8_t ls, dsk_meta; static uint32_t fs_off; static __inline uint8_t fsfind(const char *name, ufs_ino_t * ino) { static char buf[DEV_BSIZE]; struct direct *d; char *s; ssize_t n; fs_off = 0; while ((n = fsread(*ino, buf, DEV_BSIZE)) > 0) for (s = buf; s < buf + DEV_BSIZE;) { d = (void *)s; if (ls) printf("%s ", d->d_name); else if (!strcmp(name, d->d_name)) { *ino = d->d_ino; return d->d_type; } s += d->d_reclen; } if (n != -1 && ls) printf("\n"); return 0; } static ufs_ino_t lookup(const char *path) { static char name[MAXNAMLEN + 1]; const char *s; ufs_ino_t ino; ssize_t n; uint8_t dt; ino = ROOTINO; dt = DT_DIR; for (;;) { if (*path == '/') path++; if (!*path) break; for (s = path; *s && *s != '/'; s++); if ((n = s - path) > MAXNAMLEN) return 0; ls = *path == '?' && n == 1 && !*s; memcpy(name, path, n); name[n] = 0; if (dt != DT_DIR) { printf("%s: not a directory.\n", name); return (0); } if ((dt = fsfind(name, &ino)) <= 0) break; path = s; } return dt == DT_REG ? ino : 0; } /* * Possible superblock locations ordered from most to least likely. */ static int sblock_try[] = SBLOCKSEARCH; #if defined(UFS2_ONLY) #define DIP(field) dp2.field #elif defined(UFS1_ONLY) #define DIP(field) dp1.field #else #define DIP(field) fs.fs_magic == FS_UFS1_MAGIC ? dp1.field : dp2.field #endif static ssize_t fsread(ufs_ino_t inode, void *buf, size_t nbyte) { #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; char *s; 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; } s = buf; size = DIP(di_size); n = size - fs_off; + if (buf == NULL && nbyte == -1) + return n; if (nbyte > n) nbyte = n; nb = nbyte; while (nb) { lbn = lblkno(&fs, fs_off); off = blkoff(&fs, fs_off); if (lbn < NDADDR) { addr2 = DIP(di_db[lbn]); } else if (lbn < NDADDR + NINDIR(&fs)) { n = INDIRPERVBLK(&fs); addr2 = DIP(di_ib[0]); u = (u_int)(lbn - NDADDR) / n * DBPERVBLK; vbaddr = fsbtodb(&fs, addr2) + u; if (indmap != vbaddr) { if (dskread(indbuf, vbaddr, DBPERVBLK)) return -1; indmap = vbaddr; } n = (lbn - NDADDR) & (n - 1); #if defined(UFS1_ONLY) memcpy(&addr1, (ufs1_daddr_t *)indbuf + n, sizeof(ufs1_daddr_t)); addr2 = addr1; #elif defined(UFS2_ONLY) memcpy(&addr2, (ufs2_daddr_t *)indbuf + n, sizeof(ufs2_daddr_t)); #else if (fs.fs_magic == FS_UFS1_MAGIC) { memcpy(&addr1, (ufs1_daddr_t *)indbuf + n, sizeof(ufs1_daddr_t)); addr2 = addr1; } else memcpy(&addr2, (ufs2_daddr_t *)indbuf + n, sizeof(ufs2_daddr_t)); #endif } else return -1; vbaddr = fsbtodb(&fs, addr2) + (off >> VBLKSHIFT) * DBPERVBLK; vboff = off & VBLKMASK; n = sblksize(&fs, size, lbn) - (off & ~VBLKMASK); if (n > VBLKSIZE) n = VBLKSIZE; if (blkmap != vbaddr) { if (dskread(blkbuf, vbaddr, n >> DEV_BSHIFT)) return -1; blkmap = vbaddr; } n -= vboff; if (n > nb) n = nb; memcpy(s, blkbuf + vboff, n); s += n; fs_off += n; nb -= n; } return nbyte; }