1 /*- 2 * Copyright (c) 1998 Robert Nordier 3 * All rights reserved. 4 * Copyright (c) 2001 Robert Drehmel 5 * All rights reserved. 6 * Copyright (c) 2014 Nathan Whitehorn 7 * All rights reserved. 8 * Copyright (c) 2015 Eric McCorkle 9 * All rights reverved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * $FreeBSD: head/sys/boot/efi/boot1/ufs_module.c 295320 2016-02-05 15:35:33Z smh $ 33 */ 34 35 #include <stdarg.h> 36 #include <stdbool.h> 37 #include <sys/cdefs.h> 38 #include <sys/param.h> 39 #include <sys/disklabel64.h> 40 #include <sys/dtype.h> 41 #include <efi.h> 42 43 #include "boot_module.h" 44 45 static dev_info_t *devinfo; 46 static dev_info_t *devices; 47 static u_int64_t label_off; 48 49 static int 50 dskread(void *buf, u_int64_t lba, int nblk) 51 { 52 int size; 53 EFI_STATUS status; 54 55 lba += label_off / DEV_BSIZE; /* adjust for disklabel partition */ 56 lba = lba / (devinfo->dev->Media->BlockSize / DEV_BSIZE); 57 size = nblk * DEV_BSIZE; 58 59 status = devinfo->dev->ReadBlocks(devinfo->dev, 60 devinfo->dev->Media->MediaId, lba, size, buf); 61 62 if (status != EFI_SUCCESS) { 63 DPRINTF("dskread: failed dev: %p, id: %u, lba: %lu, size: %d, " 64 "status: %llu\n", devinfo->dev, 65 devinfo->dev->Media->MediaId, lba, size, 66 status); 67 return (-1); 68 } 69 70 return (0); 71 } 72 73 /* For ufsread.c */ 74 uint64_t fs_off; 75 int ls; 76 77 static struct ufs_dmadat __dmadat; 78 static struct ufs_dmadat *boot2_dmadat; 79 80 #include "ufsread.c" 81 82 #define fsread boot2_ufs_read 83 #define fsread_size boot2_ufs_read_size 84 #define lookup boot2_ufs_lookup 85 86 static int 87 init_dev(dev_info_t* dev) 88 { 89 devinfo = dev; 90 boot2_dmadat = &__dmadat; 91 struct disklabel64 *label; 92 EFI_STATUS status; 93 size_t label_size; 94 95 label_size = (sizeof(*label) + 2047) & ~(size_t)2047; 96 97 label_off = 0; 98 status = BS->AllocatePool(EfiLoaderData, label_size, (void **)&label); 99 if (status == EFI_SUCCESS) { 100 if (dskread(label, 0, label_size / DEV_BSIZE) == 0 && 101 label->d_magic == DISKMAGIC64 && 102 label->d_npartitions > 0 && 103 label->d_partitions[0].p_fstype == FS_BSDFFS) { 104 label_off = label->d_partitions[0].p_boffset; 105 } 106 BS->FreePool(label); 107 } 108 return fsread(0, NULL, 0); 109 } 110 111 static EFI_STATUS 112 probe(dev_info_t* dev) 113 { 114 115 if (init_dev(dev) < 0) 116 return (EFI_UNSUPPORTED); 117 118 add_device(&devices, dev); 119 120 return (EFI_SUCCESS); 121 } 122 123 static EFI_STATUS 124 load(const char *filepath, dev_info_t *dev, void **bufp, size_t *bufsize) 125 { 126 ufs_ino_t ino; 127 EFI_STATUS status; 128 size_t size; 129 ssize_t read; 130 void *buf; 131 132 DPRINTF("Loading '%s' from %s\n", filepath, devpath_str(dev->devpath)); 133 134 if (init_dev(dev) < 0) { 135 DPRINTF("Failed to init device\n"); 136 return (EFI_UNSUPPORTED); 137 } 138 139 if ((ino = lookup(filepath)) == 0) { 140 DPRINTF("Failed to lookup '%s' (file not found?)\n", filepath); 141 return (EFI_NOT_FOUND); 142 } 143 144 if (fsread_size(ino, NULL, 0, &size) < 0 || size <= 0) { 145 printf("Failed to read size of '%s' ino: %d\n", filepath, ino); 146 return (EFI_INVALID_PARAMETER); 147 } 148 149 if ((status = BS->AllocatePool(EfiLoaderData, size, &buf)) != 150 EFI_SUCCESS) { 151 printf("Failed to allocate read buffer %zu for '%s' (%llu)\n", 152 size, filepath, status); 153 return (status); 154 } 155 156 read = fsread(ino, buf, size); 157 if ((size_t)read != size) { 158 printf("Failed to read '%s' (%zd != %zu)\n", filepath, read, 159 size); 160 (void)BS->FreePool(buf); 161 return (EFI_INVALID_PARAMETER); 162 } 163 164 DPRINTF("Load complete\n"); 165 166 *bufp = buf; 167 *bufsize = size; 168 169 return (EFI_SUCCESS); 170 } 171 172 static void 173 status(void) 174 { 175 int i; 176 dev_info_t *dev; 177 178 for (dev = devices, i = 0; dev != NULL; dev = dev->next, i++) 179 ; 180 181 printf("%s found ", ufs_module.name); 182 switch (i) { 183 case 0: 184 printf("no partitions\n"); 185 break; 186 case 1: 187 printf("%d partition\n", i); 188 break; 189 default: 190 printf("%d partitions\n", i); 191 break; 192 } 193 } 194 195 static dev_info_t * 196 _devices(void) 197 { 198 199 return (devices); 200 } 201 202 const boot_module_t ufs_module = 203 { 204 .name = "UFS", 205 .probe = probe, 206 .load = load, 207 .status = status, 208 .devices = _devices 209 }; 210