efidisk_ll.c revision 1.1
1/* $NetBSD: efidisk_ll.c,v 1.1 2017/01/24 11:09:14 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 = BIOSDISK_TYPE_HD; 99 d->flags = BIOSDISK_INT13EXT; 100 101 ed->totsec = media->LastBlock + 1; 102 ed->sbytes = media->BlockSize; 103 ed->flags = 0; 104 if (media->RemovableMedia) 105 ed->flags |= EXTINFO_REMOVABLE; 106 107 return 0; 108} 109 110/* 111 * Global shared "diskbuf" is used as read ahead buffer. For reading from 112 * floppies, the bootstrap has to be loaded on a 64K boundary to ensure that 113 * this buffer doesn't cross a 64K DMA boundary. 114 */ 115static int ra_dev; 116static daddr_t ra_end; 117static daddr_t ra_first; 118 119static int 120do_read(struct biosdisk_ll *d, daddr_t dblk, int num, char *buf) 121{ 122 EFI_STATUS status; 123 const struct efidiskinfo *edi; 124 125 edi = efidisk_getinfo(d->dev); 126 if (edi == NULL) 127 return -1; 128 129 status = uefi_call_wrapper(edi->bio->ReadBlocks, 5, edi->bio, 130 edi->media_id, dblk, num * d->secsize, buf); 131 if (EFI_ERROR(status)) 132 return -1; 133 return num; 134} 135 136/* 137 * NB if 'cold' is set below not all of the program is loaded, so 138 * mustn't use data segment, bss, call library functions or do read-ahead. 139 */ 140int 141readsects(struct biosdisk_ll *d, daddr_t dblk, int num, char *buf, int cold) 142{ 143 while (num) { 144 int nsec; 145 146 /* check for usable data in read-ahead buffer */ 147 if (cold || diskbuf_user != &ra_dev || d->dev != ra_dev 148 || dblk < ra_first || dblk >= ra_end) { 149 150 /* no, read from disk */ 151 char *trbuf; 152 int maxsecs; 153 int retries = BIOSDISK_RETRIES; 154 155 if (cold) { 156 /* transfer directly to buffer */ 157 trbuf = buf; 158 maxsecs = num; 159 } else { 160 /* fill read-ahead buffer */ 161 trbuf = alloc_diskbuf(0); /* no data yet */ 162 maxsecs = DISKBUFSIZE / d->secsize; 163 } 164 165 while ((nsec = do_read(d, dblk, maxsecs, trbuf)) < 0) { 166#ifdef DISK_DEBUG 167 if (!cold) 168 printf("read error dblk %"PRId64"-%"PRId64"\n", 169 dblk, (dblk + maxsecs - 1)); 170#endif 171 if (--retries >= 0) 172 continue; 173 return -1; /* XXX cannot output here if 174 * (cold) */ 175 } 176 if (!cold) { 177 ra_dev = d->dev; 178 ra_first = dblk; 179 ra_end = dblk + nsec; 180 diskbuf_user = &ra_dev; 181 } 182 } else /* can take blocks from end of read-ahead 183 * buffer */ 184 nsec = ra_end - dblk; 185 186 if (!cold) { 187 /* copy data from read-ahead to user buffer */ 188 if (nsec > num) 189 nsec = num; 190 memcpy(buf, 191 diskbufp + (dblk - ra_first) * d->secsize, 192 nsec * d->secsize); 193 } 194 buf += nsec * d->secsize; 195 num -= nsec; 196 dblk += nsec; 197 } 198 199 return 0; 200} 201