Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | /* |
2 | * ========== Copyright Header Begin ========================================== | |
3 | * | |
4 | * Hypervisor Software File: prom_file.c | |
5 | * | |
6 | * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. | |
7 | * | |
8 | * - Do no alter or remove copyright notices | |
9 | * | |
10 | * - Redistribution and use of this software in source and binary forms, with | |
11 | * or without modification, are permitted provided that the following | |
12 | * conditions are met: | |
13 | * | |
14 | * - Redistribution of source code must retain the above copyright notice, | |
15 | * this list of conditions and the following disclaimer. | |
16 | * | |
17 | * - Redistribution in binary form must reproduce the above copyright notice, | |
18 | * this list of conditions and the following disclaimer in the | |
19 | * documentation and/or other materials provided with the distribution. | |
20 | * | |
21 | * Neither the name of Sun Microsystems, Inc. or the names of contributors | |
22 | * may be used to endorse or promote products derived from this software | |
23 | * without specific prior written permission. | |
24 | * | |
25 | * This software is provided "AS IS," without a warranty of any kind. | |
26 | * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, | |
27 | * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A | |
28 | * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN | |
29 | * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR | |
30 | * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR | |
31 | * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN | |
32 | * OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR | |
33 | * FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE | |
34 | * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, | |
35 | * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF | |
36 | * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. | |
37 | * | |
38 | * You acknowledge that this software is not designed, licensed or | |
39 | * intended for use in the design, construction, operation or maintenance of | |
40 | * any nuclear facility. | |
41 | * | |
42 | * ========== Copyright Header End ============================================ | |
43 | */ | |
44 | /* | |
45 | * Copyright (c) 2001-2003 Sun Microsystems, Inc. | |
46 | * All rights reserved. | |
47 | * Use is subject to license terms. | |
48 | */ | |
49 | ||
50 | #pragma ident "@(#)prom_file.c 1.1 01/04/19 SMI" | |
51 | ||
52 | #include <sys/promif.h> | |
53 | #include <sys/promimpl.h> | |
54 | ||
55 | #define BLOCKSIZE 0x1000 | |
56 | ||
57 | typedef struct DEBLOCK_T { | |
58 | long start; | |
59 | long blocksize; | |
60 | uchar_t buffer[BLOCKSIZE]; | |
61 | } deblock_t; | |
62 | ||
63 | typedef struct FILE_T { | |
64 | ihandle_t ihandle; | |
65 | long size; | |
66 | long currentpos; | |
67 | deblock_t deblock; | |
68 | } FILE; | |
69 | ||
70 | #define _FILEDEFED | |
71 | #include <stdio.h> | |
72 | ||
73 | ||
74 | /* | |
75 | * this counts on the fact that the standalone program was boot disked rather | |
76 | * than boot netted. (ufs-file-system package is already loaded) | |
77 | * By the way, isn't ufs-file-system redundant? | |
78 | */ | |
79 | ||
80 | void * | |
81 | loadfile(ihandle_t instance, uint32_t addr) | |
82 | { | |
83 | cell_t ci[8]; | |
84 | int32_t retval; | |
85 | ||
86 | ci[0] = p1275_ptr2cell("call-method"); /* Service name */ | |
87 | ci[1] = (cell_t)3; /* #argument cells */ | |
88 | ci[2] = (cell_t)2; /* #result cells */ | |
89 | ci[3] = p1275_ptr2cell("load"); /* Arg1: method name */ | |
90 | ci[4] = p1275_ihandle2cell(instance); /* Arg2:SA1:dev-node ihandle */ | |
91 | ci[5] = p1275_int2cell(addr); /* Arg3: SA2: load-addr */ | |
92 | ||
93 | retval = p1275_cif_handler(&ci); | |
94 | ||
95 | if (retval != 0) | |
96 | return ((void *)-1); | |
97 | if (ci[6] != 0) /* Res1: Catch result */ | |
98 | return ((void *)-1); | |
99 | ||
100 | return ((void *)ci[7]); /* Res2: virt addr */ | |
101 | } | |
102 | ||
103 | long | |
104 | filesize(ihandle_t instance) | |
105 | { | |
106 | cell_t ci[8]; | |
107 | int32_t retval; | |
108 | ||
109 | ci[0] = p1275_ptr2cell("call-method"); /* Service name */ | |
110 | ci[1] = (cell_t)2; /* #argument cells */ | |
111 | ci[2] = (cell_t)3; /* #result cells */ | |
112 | ci[3] = p1275_ptr2cell("size"); /* Arg1: method name */ | |
113 | ci[4] = p1275_ihandle2cell(instance); /* Arg2:SA1:dev-node ihandle */ | |
114 | ||
115 | retval = p1275_cif_handler(&ci); | |
116 | ||
117 | if (retval != 0) | |
118 | return (-1); | |
119 | if (ci[5] != 0) /* Res1: Catch result */ | |
120 | return (-1); | |
121 | /* Res2: Don't care */ | |
122 | ||
123 | return ((long)ci[7]); /* Res3: file size */ | |
124 | } | |
125 | ||
126 | long | |
127 | fileseek(ihandle_t instance, int32_t offset) | |
128 | { | |
129 | /* | |
130 | * Note that the order of the args passed in (after the ihandle) | |
131 | * is being reversed so that when they are popped onto the forth | |
132 | * stack they will be in the correct order for seeking | |
133 | * ( offset whence -- error? ) | |
134 | */ | |
135 | ||
136 | cell_t ci[9]; | |
137 | int32_t retval; | |
138 | ||
139 | ci[0] = p1275_ptr2cell("call-method"); /* Service name */ | |
140 | ci[1] = (cell_t)4; /* #argument cells */ | |
141 | ci[2] = (cell_t)2; /* #result cells */ | |
142 | ci[3] = p1275_ptr2cell("seek"); /* Arg1: method name */ | |
143 | ci[4] = p1275_ihandle2cell(instance); /* Arg2:SA1:dev-node ihandle */ | |
144 | ci[5] = p1275_int2cell(0); /* Arg3: SA3: whence */ | |
145 | ci[6] = p1275_int2cell(offset); /* Arg4: SA2: offset */ | |
146 | ||
147 | retval = p1275_cif_handler(&ci); | |
148 | ||
149 | if (retval != 0) | |
150 | return (-1); | |
151 | if (ci[7] != 0) /* Res1: Catch result */ | |
152 | return (-1); | |
153 | ||
154 | return (ci[8]); /* Res2: error? */ | |
155 | } | |
156 | ||
157 | int32_t | |
158 | fileread(ihandle_t instance, uchar_t *addr, int32_t len) | |
159 | { | |
160 | /* | |
161 | * Note that the order of the args passed in (after the ihandle) | |
162 | * is being reversed so that when they are popped onto the forth | |
163 | * stack they will be in the correct order for reading | |
164 | * ( addr len -- act-len ) | |
165 | */ | |
166 | ||
167 | cell_t ci[9]; | |
168 | int32_t retval; | |
169 | ||
170 | ci[0] = p1275_ptr2cell("call-method"); /* Service name */ | |
171 | ci[1] = (cell_t)4; /* #argument cells */ | |
172 | ci[2] = (cell_t)2; /* #result cells */ | |
173 | ci[3] = p1275_ptr2cell("read"); /* Arg1: method name */ | |
174 | ci[4] = p1275_ihandle2cell(instance); /* Arg2:SA1:dev-node ihandle */ | |
175 | ci[5] = p1275_int2cell(len); /* Arg3: SA3: length */ | |
176 | ci[6] = p1275_int2cell(addr); /* Arg4: SA2: addr */ | |
177 | ||
178 | retval = p1275_cif_handler(&ci); | |
179 | ||
180 | if (retval != 0) | |
181 | return (-1); | |
182 | if (ci[7] != 0) /* Res1: Catch result */ | |
183 | return (-1); | |
184 | ||
185 | return (ci[8]); /* Res2: actual len */ | |
186 | } | |
187 | ||
188 | /* it's always read/write */ | |
189 | FILE * | |
190 | fopen(char const *filename, char const *mode) | |
191 | { | |
192 | static FILE thisfile; | |
193 | ihandle_t ihandle; | |
194 | ||
195 | char ext_filename[100]; | |
196 | prom_strcpy(ext_filename, "disk:,"); | |
197 | filename = "|platform|platforms.di"; | |
198 | prom_strcat(ext_filename, (caddr_t)filename); | |
199 | ||
200 | if ((ihandle = prom_open(ext_filename)) == NULL) | |
201 | return (NULL); | |
202 | ||
203 | prom_printf("thisfile %x\n", thisfile); | |
204 | prom_printf("ihandle %x\n", ihandle); | |
205 | ||
206 | thisfile.size = filesize(ihandle); | |
207 | thisfile.currentpos = 0; | |
208 | thisfile.ihandle = ihandle; | |
209 | thisfile.deblock.start = -1; /* nothing read */ | |
210 | ||
211 | printf("filesize = %i\n", thisfile.size); | |
212 | ||
213 | return (&thisfile); | |
214 | } | |
215 | ||
216 | int32_t | |
217 | fclose(FILE *stream) | |
218 | { | |
219 | return (prom_close(stream->ihandle)); | |
220 | } | |
221 | ||
222 | int32_t | |
223 | fseek(FILE *stream, long offset, int32_t whence) | |
224 | { | |
225 | switch (whence) { | |
226 | case SEEK_SET: | |
227 | stream->currentpos = 0 + offset; | |
228 | break; | |
229 | case SEEK_CUR: | |
230 | stream->currentpos += offset; | |
231 | break; | |
232 | case SEEK_END: | |
233 | /* Unix allows going off the end of a stream! */ | |
234 | stream->currentpos = stream->size + offset; | |
235 | break; | |
236 | default: | |
237 | return (-1); | |
238 | } | |
239 | return (fileseek(stream->ihandle, stream->currentpos)); | |
240 | } | |
241 | ||
242 | long | |
243 | ftell(FILE *stream) | |
244 | { | |
245 | return (stream->currentpos); | |
246 | } | |
247 | ||
248 | int32_t | |
249 | min(int32_t a, int32_t b) | |
250 | { | |
251 | if (a < b) | |
252 | return (a); | |
253 | else | |
254 | return (b); | |
255 | } | |
256 | ||
257 | ||
258 | int32_t | |
259 | fgetc(FILE *stream) | |
260 | { | |
261 | /* I should buffer this */ | |
262 | ||
263 | long file_end = stream->size; | |
264 | long position = stream->currentpos; | |
265 | long size = min((stream->size - position), BLOCKSIZE); | |
266 | uchar_t *buffer = stream->deblock.buffer; | |
267 | ||
268 | if (position >= file_end) | |
269 | return (EOF); | |
270 | ||
271 | if ((position < stream->deblock.start) || | |
272 | (position >= stream->deblock.start + stream->deblock.blocksize) || | |
273 | (stream->deblock.start == -1)) { | |
274 | stream->deblock.start = position; | |
275 | stream->deblock.blocksize = size; | |
276 | if ((fileread(stream->ihandle, buffer, size)) != size) | |
277 | return (-1); | |
278 | } | |
279 | ||
280 | return ((int32_t)buffer[stream->currentpos++ - stream->deblock.start]); | |
281 | ||
282 | } |