1324709Simp/*- 2324709Simp * Copyright (c) 1998 Robert Nordier 3324709Simp * All rights reserved. 4324709Simp * Copyright (c) 2001 Robert Drehmel 5324709Simp * All rights reserved. 6324709Simp * Copyright (c) 2014 Nathan Whitehorn 7324709Simp * All rights reserved. 8324709Simp * Copyright (c) 2015 Eric McCorkle 9324709Simp * All rights reverved. 10324709Simp * 11324709Simp * Redistribution and use in source and binary forms, with or without 12324709Simp * modification, are permitted provided that the following conditions 13324709Simp * are met: 14324709Simp * 1. Redistributions of source code must retain the above copyright 15324709Simp * notice, this list of conditions and the following disclaimer. 16324709Simp * 2. Redistributions in binary form must reproduce the above copyright 17324709Simp * notice, this list of conditions and the following disclaimer in the 18324709Simp * documentation and/or other materials provided with the distribution. 19324709Simp * 20324709Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21324709Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22324709Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23324709Simp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24324709Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25324709Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26324709Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27324709Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28324709Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29324709Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30324709Simp * SUCH DAMAGE. 31324709Simp * 32324709Simp * $FreeBSD: stable/11/stand/efi/boot1/ufs_module.c 334444 2018-05-31 20:01:58Z gjb $ 33324709Simp */ 34324709Simp 35324709Simp#include <stdarg.h> 36324709Simp#include <stdbool.h> 37324709Simp#include <sys/cdefs.h> 38324709Simp#include <sys/param.h> 39334444Sgjb#include <sys/disklabel.h> 40324709Simp#include <efi.h> 41324709Simp 42324709Simp#include "boot_module.h" 43324709Simp 44334444Sgjb#define BSD_LABEL_BUFFER 8192 45334444Sgjb#define BSD_LABEL_OFFSET DEV_BSIZE 46334444Sgjb 47324709Simpstatic dev_info_t *devinfo; 48324709Simpstatic dev_info_t *devices; 49324709Simp 50324709Simpstatic int 51332154Skevansdskread(void *buf, uint64_t lba, int nblk) 52324709Simp{ 53324709Simp int size; 54324709Simp EFI_STATUS status; 55324709Simp 56334444Sgjb lba += devinfo->partoff; 57324709Simp lba = lba / (devinfo->dev->Media->BlockSize / DEV_BSIZE); 58324709Simp size = nblk * DEV_BSIZE; 59324709Simp 60324709Simp status = devinfo->dev->ReadBlocks(devinfo->dev, 61324709Simp devinfo->dev->Media->MediaId, lba, size, buf); 62324709Simp 63324709Simp if (status != EFI_SUCCESS) { 64324709Simp DPRINTF("dskread: failed dev: %p, id: %u, lba: %ju, size: %d, " 65324709Simp "status: %lu\n", devinfo->dev, 66324709Simp devinfo->dev->Media->MediaId, (uintmax_t)lba, size, 67324709Simp EFI_ERROR_CODE(status)); 68324709Simp return (-1); 69324709Simp } 70324709Simp 71324709Simp return (0); 72324709Simp} 73324709Simp 74324709Simp#include "ufsread.c" 75324709Simp 76324709Simpstatic struct dmadat __dmadat; 77324709Simp 78324709Simpstatic int 79324709Simpinit_dev(dev_info_t* dev) 80324709Simp{ 81334444Sgjb char buffer[BSD_LABEL_BUFFER]; 82334444Sgjb struct disklabel *dl; 83334444Sgjb uint64_t bs; 84334444Sgjb int ok; 85324709Simp 86324709Simp devinfo = dev; 87324709Simp dmadat = &__dmadat; 88324709Simp 89334444Sgjb /* 90334444Sgjb * First try offset 0. This is the typical GPT case where we have no 91334444Sgjb * further partitioning (as well as the degenerate MBR case where 92334444Sgjb * the bsdlabel has a 0 offset). 93334444Sgjb */ 94334444Sgjb devinfo->partoff = 0; 95334444Sgjb ok = fsread(0, NULL, 0); 96334444Sgjb if (ok >= 0) 97334444Sgjb return (ok); 98334444Sgjb 99334444Sgjb /* 100334444Sgjb * Next, we look for a bsdlabel. This is technically located in sector 101334444Sgjb * 1. For 4k sectors, this offset is 4096, for 512b sectors it's 102334444Sgjb * 512. However, we have to fall back to 512 here because we create 103334444Sgjb * images that assume 512 byte blocks, but these can be put on devices 104334444Sgjb * who have 4k (or other) block sizes. If there's a crazy block size, we 105334444Sgjb * skip the 'at one sector' and go stright to checking at 512 bytes. 106334444Sgjb * There are other offsets that are historic, but we don't probe those 107334444Sgjb * since they were never used for MBR disks on FreeBSD on systems that 108334444Sgjb * could boot UEFI. UEFI is little endian only, as are BSD labels. We 109334444Sgjb * will retry fsread(0) only if there's a label found with a non-zero 110334444Sgjb * offset. 111334444Sgjb */ 112334444Sgjb if (dskread(buffer, 0, BSD_LABEL_BUFFER / DEV_BSIZE) != 0) 113334444Sgjb return (-1); 114334444Sgjb dl = NULL; 115334444Sgjb bs = devinfo->dev->Media->BlockSize; 116334444Sgjb if (bs != 0 && bs <= BSD_LABEL_BUFFER / 2) 117334444Sgjb dl = (struct disklabel *)&buffer[bs]; 118334444Sgjb if (dl == NULL || dl->d_magic != DISKMAGIC || dl->d_magic2 != DISKMAGIC) 119334444Sgjb dl = (struct disklabel *)&buffer[BSD_LABEL_OFFSET]; 120334444Sgjb if (dl->d_magic != DISKMAGIC || dl->d_magic2 != DISKMAGIC || 121334444Sgjb dl->d_partitions[0].p_offset == 0) 122334444Sgjb return (-1); 123334444Sgjb devinfo->partoff = dl->d_partitions[0].p_offset; 124334444Sgjb return (fsread(0, NULL, 0)); 125324709Simp} 126324709Simp 127324709Simpstatic EFI_STATUS 128324709Simpprobe(dev_info_t* dev) 129324709Simp{ 130324709Simp 131324709Simp if (init_dev(dev) < 0) 132324709Simp return (EFI_UNSUPPORTED); 133324709Simp 134324709Simp add_device(&devices, dev); 135324709Simp 136324709Simp return (EFI_SUCCESS); 137324709Simp} 138324709Simp 139324709Simpstatic EFI_STATUS 140324709Simpload(const char *filepath, dev_info_t *dev, void **bufp, size_t *bufsize) 141324709Simp{ 142324709Simp ufs_ino_t ino; 143324709Simp EFI_STATUS status; 144324709Simp size_t size; 145324709Simp ssize_t read; 146324709Simp void *buf; 147324709Simp 148324709Simp#ifdef EFI_DEBUG 149324709Simp { 150324709Simp CHAR16 *text = efi_devpath_name(dev->devpath); 151324709Simp DPRINTF("Loading '%s' from %S\n", filepath, text); 152324709Simp efi_free_devpath_name(text); 153324709Simp } 154324709Simp#endif 155324709Simp if (init_dev(dev) < 0) { 156324709Simp DPRINTF("Failed to init device\n"); 157324709Simp return (EFI_UNSUPPORTED); 158324709Simp } 159324709Simp 160324709Simp if ((ino = lookup(filepath)) == 0) { 161324709Simp DPRINTF("Failed to lookup '%s' (file not found?)\n", filepath); 162324709Simp return (EFI_NOT_FOUND); 163324709Simp } 164324709Simp 165324709Simp if (fsread_size(ino, NULL, 0, &size) < 0 || size <= 0) { 166324709Simp printf("Failed to read size of '%s' ino: %d\n", filepath, ino); 167324709Simp return (EFI_INVALID_PARAMETER); 168324709Simp } 169324709Simp 170324709Simp if ((status = BS->AllocatePool(EfiLoaderData, size, &buf)) != 171324709Simp EFI_SUCCESS) { 172324709Simp printf("Failed to allocate read buffer %zu for '%s' (%lu)\n", 173324709Simp size, filepath, EFI_ERROR_CODE(status)); 174324709Simp return (status); 175324709Simp } 176324709Simp 177324709Simp read = fsread(ino, buf, size); 178324709Simp if ((size_t)read != size) { 179324709Simp printf("Failed to read '%s' (%zd != %zu)\n", filepath, read, 180324709Simp size); 181324709Simp (void)BS->FreePool(buf); 182324709Simp return (EFI_INVALID_PARAMETER); 183324709Simp } 184324709Simp 185324709Simp DPRINTF("Load complete\n"); 186324709Simp 187324709Simp *bufp = buf; 188324709Simp *bufsize = size; 189324709Simp 190324709Simp return (EFI_SUCCESS); 191324709Simp} 192324709Simp 193324709Simpstatic void 194324709Simpstatus(void) 195324709Simp{ 196324709Simp int i; 197324709Simp dev_info_t *dev; 198324709Simp 199324709Simp for (dev = devices, i = 0; dev != NULL; dev = dev->next, i++) 200324709Simp ; 201324709Simp 202324709Simp printf("%s found ", ufs_module.name); 203324709Simp switch (i) { 204324709Simp case 0: 205324709Simp printf("no partitions\n"); 206324709Simp break; 207324709Simp case 1: 208324709Simp printf("%d partition\n", i); 209324709Simp break; 210324709Simp default: 211324709Simp printf("%d partitions\n", i); 212324709Simp } 213324709Simp} 214324709Simp 215324709Simpstatic dev_info_t * 216324709Simp_devices(void) 217324709Simp{ 218324709Simp 219324709Simp return (devices); 220324709Simp} 221324709Simp 222324709Simpconst boot_module_t ufs_module = 223324709Simp{ 224324709Simp .name = "UFS", 225324709Simp .probe = probe, 226324709Simp .load = load, 227324709Simp .status = status, 228324709Simp .devices = _devices 229324709Simp}; 230