Home | History | Annotate | Line # | Download | only in efiboot
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 
     79 static int do_read(struct biosdisk_ll *, daddr_t, int, char *);
     80 
     81 #ifndef BIOSDISK_RETRIES
     82 #define BIOSDISK_RETRIES 5
     83 #endif
     84 
     85 int
     86 set_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  */
    115 static int      ra_dev;
    116 static daddr_t  ra_end;
    117 static daddr_t  ra_first;
    118 
    119 static int
    120 do_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  */
    140 int
    141 readsects(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