1/* $NetBSD: efidisk_ll.c,v 1.2 2018/03/08 10:34:33 nonaka Exp $ */ 2/* NetBSD: biosdisk_ll.c,v 1.31 2011/02/21 02:58:02 jakllsch Exp */ 3 4/*- 5 * Copyright (c) 2005 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Bang Jun-Young. 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33/* 34 * Copyright (c) 1996 35 * Matthias Drochner. All rights reserved. 36 * Copyright (c) 1996 37 * Perry E. Metzger. All rights reserved. 38 * 39 * Redistribution and use in source and binary forms, with or without 40 * modification, are permitted provided that the following conditions 41 * are met: 42 * 1. Redistributions of source code must retain the above copyright 43 * notice, this list of conditions and the following disclaimer. 44 * 2. Redistributions in binary form must reproduce the above copyright 45 * notice, this list of conditions and the following disclaimer in the 46 * documentation and/or other materials provided with the distribution. 47 * 3. All advertising materials mentioning features or use of this software 48 * must display the following acknowledgements: 49 * This product includes software developed for the NetBSD Project 50 * by Matthias Drochner. 51 * This product includes software developed for the NetBSD Project 52 * by Perry E. Metzger. 53 * 4. The names of the authors may not be used to endorse or promote products 54 * derived from this software without specific prior written permission. 55 * 56 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 57 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 58 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 59 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 60 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 61 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 62 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 63 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 64 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 65 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 66 */ 67 68/* 69 * shared by bootsector startup (bootsectmain) and biosdisk.c 70 * needs lowlevel parts from bios_disk.S 71 */ 72 73#include "efiboot.h" 74 75#include "biosdisk_ll.h" 76#include "diskbuf.h" 77#include "efidisk.h" 78 79static int do_read(struct biosdisk_ll *, daddr_t, int, char *); 80 81#ifndef BIOSDISK_RETRIES 82#define BIOSDISK_RETRIES 5 83#endif 84 85int 86set_geometry(struct biosdisk_ll *d, struct biosdisk_extinfo *ed) 87{ 88 const struct efidiskinfo *edi; 89 EFI_BLOCK_IO_MEDIA *media; 90 91 edi = efidisk_getinfo(d->dev); 92 if (edi == NULL) 93 return 1; 94 95 media = edi->bio->Media; 96 97 d->secsize = media->BlockSize; 98 d->type = edi->type; 99 d->flags = BIOSDISK_INT13EXT; 100 101 if (ed != NULL) { 102 ed->totsec = media->LastBlock + 1; 103 ed->sbytes = media->BlockSize; 104 ed->flags = 0; 105 if (media->RemovableMedia) 106 ed->flags |= EXTINFO_REMOVABLE; 107 } 108 109 return 0; 110} 111 112/* 113 * Global shared "diskbuf" is used as read ahead buffer. For reading from 114 * floppies, the bootstrap has to be loaded on a 64K boundary to ensure that 115 * this buffer doesn't cross a 64K DMA boundary. 116 */ 117static int ra_dev; 118static daddr_t ra_end; 119static daddr_t ra_first; 120 121static int 122do_read(struct biosdisk_ll *d, daddr_t dblk, int num, char *buf) 123{ 124 EFI_STATUS status; 125 const struct efidiskinfo *edi; 126 127 edi = efidisk_getinfo(d->dev); 128 if (edi == NULL) 129 return -1; 130 131 status = uefi_call_wrapper(edi->bio->ReadBlocks, 5, edi->bio, 132 edi->media_id, dblk, num * d->secsize, buf); 133 if (EFI_ERROR(status)) 134 return -1; 135 return num; 136} 137 138/* 139 * NB if 'cold' is set below not all of the program is loaded, so 140 * mustn't use data segment, bss, call library functions or do read-ahead. 141 */ 142int 143readsects(struct biosdisk_ll *d, daddr_t dblk, int num, char *buf, int cold) 144{ 145 while (num) { 146 int nsec; 147 148 /* check for usable data in read-ahead buffer */ 149 if (cold || diskbuf_user != &ra_dev || d->dev != ra_dev 150 || dblk < ra_first || dblk >= ra_end) { 151 152 /* no, read from disk */ 153 char *trbuf; 154 int maxsecs; 155 int retries = BIOSDISK_RETRIES; 156 157 if (cold) { 158 /* transfer directly to buffer */ 159 trbuf = buf; 160 maxsecs = num; 161 } else { 162 /* fill read-ahead buffer */ 163 trbuf = alloc_diskbuf(0); /* no data yet */ 164 maxsecs = DISKBUFSIZE / d->secsize; 165 } 166 167 while ((nsec = do_read(d, dblk, maxsecs, trbuf)) < 0) { 168#ifdef DISK_DEBUG 169 if (!cold) 170 printf("read error dblk %"PRId64"-%"PRId64"\n", 171 dblk, (dblk + maxsecs - 1)); 172#endif 173 if (--retries >= 0) 174 continue; 175 return -1; /* XXX cannot output here if 176 * (cold) */ 177 } 178 if (!cold) { 179 ra_dev = d->dev; 180 ra_first = dblk; 181 ra_end = dblk + nsec; 182 diskbuf_user = &ra_dev; 183 } 184 } else /* can take blocks from end of read-ahead 185 * buffer */ 186 nsec = ra_end - dblk; 187 188 if (!cold) { 189 /* copy data from read-ahead to user buffer */ 190 if (nsec > num) 191 nsec = num; 192 memcpy(buf, 193 diskbufp + (dblk - ra_first) * d->secsize, 194 nsec * d->secsize); 195 } 196 buf += nsec * d->secsize; 197 num -= nsec; 198 dblk += nsec; 199 } 200 201 return 0; 202} 203