Switch dir over to use the new static filesystem dir methods.
[openbios.git] / packages / sun-parts.c
blobbe26855ae9e4216dbb03226e8b93ef90dd0fda27
1 /*
2 * Sun (Sparc32/64) partition support
4 * Copyright (C) 2004 Stefan Reinauer
6 * This code is based (and copied in many places) from
7 * mac partition support by Samuel Rydh (samuel@ibrium.se)
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
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"
22 //#define DEBUG_SUN_PARTS
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
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;
39 DECLARE_NODE( sunparts, INSTALL_OPEN, sizeof(sunparts_info_t), "+/packages/sun-parts" );
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(); })
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 uint8_t spare1;
50 uint8_t id;
51 uint8_t spare2;
52 uint8_t flags;
53 } infos[8];
54 uint8_t spare[246]; /* Boot information etc. */
55 uint16_t rspeed; /* Disk rotational speed */
56 uint16_t pcylcount; /* Physical cylinder count */
57 uint16_t sparecyl; /* extra sects per cylinder */
58 uint8_t spare2[4]; /* More magic... */
59 uint16_t ilfact; /* Interleave factor */
60 uint16_t ncyl; /* Data cylinder count */
61 uint16_t nacyl; /* Alt. cylinder count */
62 uint16_t ntrks; /* Tracks per cylinder */
63 uint16_t nsect; /* Sectors per track */
64 uint8_t spare3[4]; /* Even more magic... */
65 struct sun_partition {
66 uint32_t start_cylinder;
67 uint32_t num_sectors;
68 } partitions[8];
69 uint16_t magic; /* Magic number */
70 uint16_t csum; /* Label xor'd checksum */
73 /* two helper functions */
75 static inline int
76 has_sun_part_magic(unsigned char *sect)
78 struct sun_disklabel *p = (struct sun_disklabel *)sect;
79 uint16_t csum, *ush, tmp16;
81 if (__be16_to_cpu(p->magic) != 0xDABE)
82 return 0;
84 csum = 0;
85 for (ush = (uint16_t *)p; ush < (uint16_t *)(p + 1); ush++) {
86 tmp16 = __be16_to_cpu(*ush);
87 csum ^= tmp16;
89 return csum == 0;
92 /* ( open -- flag ) */
93 static void
94 sunparts_open( sunparts_info_t *di )
96 char *str = my_args_copy();
97 char *argstr = strdup("");
98 char *parstr = strdup("");
99 int parnum = -1;
100 unsigned char buf[512];
101 struct sun_disklabel *p;
102 unsigned int i, bs;
103 ducell offs, size;
104 phandle_t ph;
106 DPRINTF("sunparts_open '%s'\n", str );
109 Arguments that we accept:
110 id: [0-7] | [a-h]
111 [(id)][,][filespec]
114 if( str ) {
115 if ( !strlen(str) )
116 parnum = -1;
117 else {
118 /* Detect the boot parameters */
119 char *ptr;
120 ptr = str;
122 /* <id>,<file> */
123 if (((*ptr >= '0' && *ptr <= '9') || (*ptr >= 'a' && *ptr <= 'a' + 8)) && *(ptr + 1) == ',') {
124 parstr = ptr;
125 *(ptr + 1) = '\0';
126 argstr = ptr + 2;
129 /* <id> */
130 else if (((*ptr >= '0' && *ptr <= '9') || (*ptr >= 'a' && *ptr <= 'a' + 8)) && *(ptr + 1) == '\0') {
131 parstr = ptr;
134 /* ,<file> */
135 else if (*ptr == ',') {
136 argstr = ptr + 1;
139 /* <file> */
140 else {
141 argstr = str;
144 /* Convert the id to a partition number */
145 if (strlen(parstr)) {
146 if (parstr[0] >= 'a' && parstr[0] < ('a' + 8))
147 parnum = parstr[0] - 'a';
148 else
149 parnum = atol(parstr);
154 DPRINTF("parstr: %s argstr: %s parnum: %d\n", parstr, argstr, parnum);
156 di->filesystem_ph = 0;
157 di->read_xt = find_parent_method("read");
158 di->seek_xt = find_parent_method("seek");
160 SEEK( 0 );
161 if( READ(buf, 512) != 512 )
162 RET(0);
164 /* Check Magic */
165 if (!has_sun_part_magic(buf)) {
166 DPRINTF("Sun partition magic not found.\n");
167 RET(0);
170 bs = 512;
171 /* get partition data */
172 p = (struct sun_disklabel *)buf;
174 for (i = 0; i < 8; i++) {
175 DPRINTF("%c: %d + %d, id %x, flags %x\n", 'a' + i, p->partitions[i].start_cylinder,
176 p->partitions[i].num_sectors, p->infos[i].id, p->infos[i].flags);
177 if (parnum < 0) {
178 if (p->partitions[i].num_sectors != 0 && p->infos[i].id != 0)
179 parnum = i;
183 if (parnum < 0)
184 parnum = 0;
186 DPRINTF("Selected partition %d\n", parnum);
188 offs = (llong)__be32_to_cpu(p->partitions[parnum].start_cylinder) *
189 __be16_to_cpu(p->ntrks) * __be16_to_cpu(p->nsect) * bs;
191 di->offs_hi = offs >> BITS;
192 di->offs_lo = offs & (ucell) -1;
193 size = (llong)__be32_to_cpu(p->partitions[parnum].num_sectors) * bs;
194 di->size_hi = size >> BITS;
195 di->size_lo = size & (ucell) -1;
196 di->type = __be32_to_cpu(p->infos[parnum].id);
198 DPRINTF("Found Sun partition, offs %lld size %lld\n",
199 (llong)offs, (llong)size);
201 /* Probe for filesystem at current offset */
202 DPRINTF("sun-parts: about to probe for fs\n");
203 DPUSH( offs );
204 PUSH_ih( my_parent() );
205 parword("find-filesystem");
206 DPRINTF("sun-parts: done fs probe\n");
208 ph = POP_ph();
209 if( ph ) {
210 DPRINTF("sun-parts: filesystem found with ph " FMT_ucellx " and args %s\n", ph, argstr);
211 di->filesystem_ph = ph;
213 /* If we have been asked to open a particular file, interpose the filesystem package with
214 the passed filename as an argument */
215 if (strlen(argstr)) {
216 push_str( argstr );
217 PUSH_ph( ph );
218 fword("interpose");
220 } else {
221 DPRINTF("sun-parts: no filesystem found; bypassing misc-files interpose\n");
224 free( str );
225 RET( -1 );
228 /* ( block0 -- flag? ) */
229 static void
230 sunparts_probe( __attribute__((unused))sunparts_info_t *dummy )
232 unsigned char *buf = (unsigned char *)POP();
234 DPRINTF("probing for Sun partitions\n");
236 RET ( has_sun_part_magic(buf) );
239 /* ( -- type offset.d size.d ) */
240 static void
241 sunparts_get_info( sunparts_info_t *di )
243 DPRINTF("Sun get_info\n");
244 PUSH( di->type );
245 PUSH( di->offs_lo );
246 PUSH( di->offs_hi );
247 PUSH( di->size_lo );
248 PUSH( di->size_hi );
251 static void
252 sunparts_block_size( __attribute__((unused))sunparts_info_t *di )
254 PUSH(512);
257 static void
258 sunparts_initialize( __attribute__((unused))sunparts_info_t *di )
260 fword("register-partition-package");
263 /* ( pos.d -- status ) */
264 static void
265 sunparts_seek(sunparts_info_t *di )
267 llong pos = DPOP();
268 llong offs;
270 DPRINTF("sunparts_seek %llx:\n", pos);
272 /* Calculate the seek offset for the parent */
273 offs = ((ducell)di->offs_hi << BITS) | di->offs_lo;
274 offs += pos;
275 DPUSH(offs);
277 DPRINTF("sunparts_seek parent offset %llx:\n", offs);
279 call_package(di->seek_xt, my_parent());
282 /* ( buf len -- actlen ) */
283 static void
284 sunparts_read(sunparts_info_t *di )
286 DPRINTF("sunparts_read\n");
288 /* Pass the read back up to the parent */
289 call_package(di->read_xt, my_parent());
292 /* ( addr -- size ) */
293 static void
294 sunparts_load( __attribute__((unused))sunparts_info_t *di )
296 /* Invoke the loader */
297 load(my_self());
300 /* ( pathstr len -- ) */
301 static void
302 sunparts_dir( sunparts_info_t *di )
304 if ( di->filesystem_ph) {
305 PUSH( my_self() );
306 push_str("dir");
307 PUSH( di->filesystem_ph );
308 fword("find-method");
309 POP();
310 fword("execute");
311 } else {
312 forth_printf("sun-parts: Unable to determine filesystem\n");
313 POP();
314 POP();
318 NODE_METHODS( sunparts ) = {
319 { "probe", sunparts_probe },
320 { "open", sunparts_open },
321 { "get-info", sunparts_get_info },
322 { "block-size", sunparts_block_size },
323 { "seek", sunparts_seek },
324 { "read", sunparts_read },
325 { "load", sunparts_load },
326 { "dir", sunparts_dir },
327 { NULL, sunparts_initialize },
330 void
331 sunparts_init( void )
333 REGISTER_NODE( sunparts );