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