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