Home | History | Annotate | Line # | Download | only in efiboot
      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 
     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 = 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  */
    117 static int      ra_dev;
    118 static daddr_t  ra_end;
    119 static daddr_t  ra_first;
    120 
    121 static int
    122 do_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  */
    142 int
    143 readsects(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