|
|
1.1 root 1: /*
2: * Sun (Sparc32/64) partition support
3: *
4: * Copyright (C) 2004 Stefan Reinauer
5: *
6: * This code is based (and copied in many places) from
7: * mac partition support by Samuel Rydh ([email protected])
8: *
9: * This program is free software; you can redistribute it and/or
10: * modify it under the terms of the GNU General Public License
11: * version 2
12: *
13: */
14:
15: #include "config.h"
16: #include "libopenbios/bindings.h"
17: #include "libopenbios/load.h"
18: #include "libc/byteorder.h"
19: #include "libc/vsprintf.h"
20: #include "packages.h"
21:
22: //#define DEBUG_SUN_PARTS
23:
24: #ifdef DEBUG_SUN_PARTS
25: #define DPRINTF(fmt, args...) \
26: do { printk(fmt , ##args); } while (0)
27: #else
28: #define DPRINTF(fmt, args...)
29: #endif
30:
31: typedef struct {
32: xt_t seek_xt, read_xt;
33: ucell offs_hi, offs_lo;
34: ucell size_hi, size_lo;
35: int type;
36: phandle_t filesystem_ph;
37: } sunparts_info_t;
38:
39: DECLARE_NODE( sunparts, INSTALL_OPEN, sizeof(sunparts_info_t), "+/packages/sun-parts" );
40:
41: #define SEEK( pos ) ({ DPUSH(pos); call_parent(di->seek_xt); POP(); })
42: #define READ( buf, size ) ({ PUSH((ucell)buf); PUSH(size); call_parent(di->read_xt); POP(); })
43:
44: /* Layout of SUN partition table */
45: struct sun_disklabel {
46: uint8_t info[128]; /* Informative text string */
47: uint8_t spare0[14];
48: struct sun_info {
49: uint16_t id;
50: uint16_t flags;
51: } infos[8];
52: uint8_t spare[246]; /* Boot information etc. */
53: uint16_t rspeed; /* Disk rotational speed */
54: uint16_t pcylcount; /* Physical cylinder count */
55: uint16_t sparecyl; /* extra sects per cylinder */
56: uint8_t spare2[4]; /* More magic... */
57: uint16_t ilfact; /* Interleave factor */
58: uint16_t ncyl; /* Data cylinder count */
59: uint16_t nacyl; /* Alt. cylinder count */
60: uint16_t ntrks; /* Tracks per cylinder */
61: uint16_t nsect; /* Sectors per track */
62: uint8_t spare3[4]; /* Even more magic... */
63: struct sun_partition {
64: uint32_t start_cylinder;
65: uint32_t num_sectors;
66: } partitions[8];
67: uint16_t magic; /* Magic number */
68: uint16_t csum; /* Label xor'd checksum */
69: };
70:
71: /* two helper functions */
72:
73: static inline int
74: has_sun_part_magic(unsigned char *sect)
75: {
76: struct sun_disklabel *p = (struct sun_disklabel *)sect;
77: uint16_t csum, *ush, tmp16;
78:
79: if (__be16_to_cpu(p->magic) != 0xDABE)
80: return 0;
81:
82: csum = 0;
83: for (ush = (uint16_t *)p; ush < (uint16_t *)(p + 1); ush++) {
84: tmp16 = __be16_to_cpu(*ush);
85: csum ^= tmp16;
86: }
87: return csum == 0;
88: }
89:
90: /* ( open -- flag ) */
91: static void
92: sunparts_open( sunparts_info_t *di )
93: {
94: char *str = my_args_copy();
95: char *argstr = NULL;
96: char *parstr = NULL;
97: int parnum = -1;
98: unsigned char buf[512];
99: struct sun_disklabel *p;
100: unsigned int i, bs;
101: ducell offs, size;
102: phandle_t ph;
103:
104: DPRINTF("sunparts_open '%s'\n", str );
105:
106: /*
107: Arguments that we accept:
108: id: [0-7] | [a-h]
109: [(id)][,][filespec]
110: */
111:
112: if( str ) {
113: if ( !strlen(str) )
114: parnum = -1;
115: else {
116: /* Detect the boot parameters */
117: char *ptr;
118: ptr = str;
119:
120: /* <id>,<file> */
121: if (((*ptr >= '0' && *ptr <= '9') || (*ptr >= 'a' && *ptr <= 'a' + 8)) && *(ptr + 1) == ',') {
122: parstr = ptr;
123: *(ptr + 1) = '\0';
124: argstr = ptr + 2;
125: }
126:
127: /* <id> */
128: else if (((*ptr >= '0' && *ptr <= '9') || (*ptr >= 'a' && *ptr <= 'a' + 8)) && *(ptr + 1) == '\0') {
129: parstr = ptr;
130: }
131:
132: /* ,<file> */
133: else if (*ptr == ',') {
134: argstr = ptr + 1;
135: }
136:
137: /* <file> */
138: else {
139: argstr = str;
140: }
141:
142: /* Convert the id to a partition number */
143: if (parstr && strlen(parstr)) {
144: if (parstr[0] >= 'a' && parstr[0] < ('a' + 8))
145: parnum = parstr[0] - 'a';
146: else
147: parnum = atol(parstr);
148: }
149: }
150: }
151:
152: DPRINTF("parstr: %s argstr: %s parnum: %d\n", parstr, argstr, parnum);
153:
154: di->filesystem_ph = 0;
155: di->read_xt = find_parent_method("read");
156: di->seek_xt = find_parent_method("seek");
157:
158: SEEK( 0 );
159: if (READ(buf, 512) != 512) {
160: free(str);
161: RET(0);
162: }
163:
164: /* Check Magic */
165: if (!has_sun_part_magic(buf)) {
166: DPRINTF("Sun partition magic not found.\n");
167: free(str);
168: RET(0);
169: }
170:
171: bs = 512;
172: /* get partition data */
173: p = (struct sun_disklabel *)buf;
174:
175: for (i = 0; i < 8; i++) {
176: DPRINTF("%c: %d + %d, id %x, flags %x\n", 'a' + i,
177: __be32_to_cpu(p->partitions[i].start_cylinder),
178: __be32_to_cpu(p->partitions[i].num_sectors),
179: __be16_to_cpu(p->infos[i].id),
180: __be16_to_cpu(p->infos[i].flags));
181: }
182:
183: if (parnum < 0)
184: parnum = 0;
185:
186: DPRINTF("Selected partition %d\n", parnum);
187:
188: offs = (long long)__be32_to_cpu(p->partitions[parnum].start_cylinder) *
189: __be16_to_cpu(p->ntrks) * __be16_to_cpu(p->nsect) * bs;
190:
191: di->offs_hi = offs >> BITS;
192: di->offs_lo = offs & (ucell) -1;
193: size = (long long)__be32_to_cpu(p->partitions[parnum].num_sectors) * bs;
194: if (size == 0) {
195: DPRINTF("Partition size is 0, exiting\n");
196: free(str);
197: RET(0);
198: }
199: di->size_hi = size >> BITS;
200: di->size_lo = size & (ucell) -1;
201: di->type = __be16_to_cpu(p->infos[parnum].id);
202:
203: DPRINTF("Found Sun partition, offs %lld size %lld\n",
204: (long long)offs, (long long)size);
205:
206: /* Probe for filesystem at current offset */
207: DPRINTF("sun-parts: about to probe for fs\n");
208: DPUSH( offs );
209: PUSH_ih( my_parent() );
210: parword("find-filesystem");
211: DPRINTF("sun-parts: done fs probe\n");
212:
213: ph = POP_ph();
214: if( ph ) {
215: DPRINTF("sun-parts: filesystem found with ph " FMT_ucellx " and args %s\n", ph, argstr);
216: di->filesystem_ph = ph;
217:
218: /* If we have been asked to open a particular file, interpose the filesystem package with
219: the passed filename as an argument */
220: if (argstr && strlen(argstr)) {
221: push_str( argstr );
222: PUSH_ph( ph );
223: fword("interpose");
224: }
225: } else {
226: DPRINTF("sun-parts: no filesystem found; bypassing misc-files interpose\n");
227:
228: /* Solaris Fcode boot blocks assume that the disk-label package will always
229: automatically interpose the "ufs-file-system" package if it exists! We
230: need to mimic this behaviour in order for the boot to work. */
231: push_str("ufs-file-system");
232: feval("find-package");
233: ph = POP_ph();
234:
235: if (argstr && ph) {
236: ph = POP_ph();
237: push_str(argstr);
238: PUSH_ph(ph);
239: fword("interpose");
240: }
241: }
242:
243: free( str );
244: RET( -1 );
245: }
246:
247: /* ( block0 -- flag? ) */
248: static void
249: sunparts_probe( __attribute__((unused))sunparts_info_t *dummy )
250: {
251: unsigned char *buf = (unsigned char *)POP();
252:
253: DPRINTF("probing for Sun partitions\n");
254:
255: RET ( has_sun_part_magic(buf) );
256: }
257:
258: /* ( -- type offset.d size.d ) */
259: static void
260: sunparts_get_info( sunparts_info_t *di )
261: {
262: DPRINTF("Sun get_info\n");
263: PUSH( di->type );
264: PUSH( di->offs_lo );
265: PUSH( di->offs_hi );
266: PUSH( di->size_lo );
267: PUSH( di->size_hi );
268: }
269:
270: static void
271: sunparts_block_size( __attribute__((unused))sunparts_info_t *di )
272: {
273: PUSH(512);
274: }
275:
276: static void
277: sunparts_initialize( __attribute__((unused))sunparts_info_t *di )
278: {
279: fword("register-partition-package");
280: }
281:
282: /* ( pos.d -- status ) */
283: static void
284: sunparts_seek(sunparts_info_t *di )
285: {
286: long long pos = DPOP();
287: long long offs, size;;
288:
289: DPRINTF("sunparts_seek %llx:\n", pos);
290:
291: /* Seek is invalid if we reach the end of the device */
292: size = ((ducell)di->size_hi << BITS) | di->size_lo;
293: if (pos > size)
294: RET( -1 );
295:
296: /* Calculate the seek offset for the parent */
297: offs = ((ducell)di->offs_hi << BITS) | di->offs_lo;
298: offs += pos;
299: DPUSH(offs);
300:
301: DPRINTF("sunparts_seek parent offset %llx:\n", offs);
302:
303: call_package(di->seek_xt, my_parent());
304: }
305:
306: /* ( buf len -- actlen ) */
307: static void
308: sunparts_read(sunparts_info_t *di )
309: {
310: DPRINTF("sunparts_read\n");
311:
312: /* Pass the read back up to the parent */
313: call_package(di->read_xt, my_parent());
314: }
315:
316: /* ( addr -- size ) */
317: static void
318: sunparts_load( __attribute__((unused))sunparts_info_t *di )
319: {
320: /* Invoke the loader */
321: load(my_self());
322: }
323:
324: /* ( pathstr len -- ) */
325: static void
326: sunparts_dir( sunparts_info_t *di )
327: {
328: if ( di->filesystem_ph) {
329: PUSH( my_self() );
330: push_str("dir");
331: PUSH( di->filesystem_ph );
332: fword("find-method");
333: POP();
334: fword("execute");
335: } else {
336: forth_printf("sun-parts: Unable to determine filesystem\n");
337: POP();
338: POP();
339: }
340: }
341:
342: NODE_METHODS( sunparts ) = {
343: { "probe", sunparts_probe },
344: { "open", sunparts_open },
345: { "get-info", sunparts_get_info },
346: { "block-size", sunparts_block_size },
347: { "seek", sunparts_seek },
348: { "read", sunparts_read },
349: { "load", sunparts_load },
350: { "dir", sunparts_dir },
351: { NULL, sunparts_initialize },
352: };
353:
354: void
355: sunparts_init( void )
356: {
357: REGISTER_NODE( sunparts );
358: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.