Introduce [u]intptr_t type
[openbios/afaerber.git] / packages / sun-parts.c
blob532651c2da0dfc1b2ac883bb57c977d7659e0ba7
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 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 */
71 /* two helper functions */
73 static inline int
74 has_sun_part_magic(unsigned char *sect)
76 struct sun_disklabel *p = (struct sun_disklabel *)sect;
77 uint16_t csum, *ush, tmp16;
79 if (__be16_to_cpu(p->magic) != 0xDABE)
80 return 0;
82 csum = 0;
83 for (ush = (uint16_t *)p; ush < (uint16_t *)(p + 1); ush++) {
84 tmp16 = __be16_to_cpu(*ush);
85 csum ^= tmp16;
87 return csum == 0;
90 /* ( open -- flag ) */
91 static void
92 sunparts_open( sunparts_info_t *di )
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;
104 DPRINTF("sunparts_open '%s'\n", str );
107 Arguments that we accept:
108 id: [0-7] | [a-h]
109 [(id)][,][filespec]
112 if( str ) {
113 if ( !strlen(str) )
114 parnum = -1;
115 else {
116 /* Detect the boot parameters */
117 char *ptr;
118 ptr = str;
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;
127 /* <id> */
128 else if (((*ptr >= '0' && *ptr <= '9') || (*ptr >= 'a' && *ptr <= 'a' + 8)) && *(ptr + 1) == '\0') {
129 parstr = ptr;
132 /* ,<file> */
133 else if (*ptr == ',') {
134 argstr = ptr + 1;
137 /* <file> */
138 else {
139 argstr = str;
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);
152 DPRINTF("parstr: %s argstr: %s parnum: %d\n", parstr, argstr, parnum);
154 di->filesystem_ph = 0;
155 di->read_xt = find_parent_method("read");
156 di->seek_xt = find_parent_method("seek");
158 SEEK( 0 );
159 if (READ(buf, 512) != 512) {
160 free(str);
161 RET(0);
164 /* Check Magic */
165 if (!has_sun_part_magic(buf)) {
166 DPRINTF("Sun partition magic not found.\n");
167 free(str);
168 RET(0);
171 bs = 512;
172 /* get partition data */
173 p = (struct sun_disklabel *)buf;
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));
183 if (parnum < 0)
184 parnum = 0;
186 DPRINTF("Selected partition %d\n", parnum);
188 offs = (long long)__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 = (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);
199 di->size_hi = size >> BITS;
200 di->size_lo = size & (ucell) -1;
201 di->type = __be16_to_cpu(p->infos[parnum].id);
203 DPRINTF("Found Sun partition, offs %lld size %lld\n",
204 (long long)offs, (long long)size);
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");
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;
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");
225 } else {
226 DPRINTF("sun-parts: no filesystem found; bypassing misc-files interpose\n");
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();
235 if (argstr && ph) {
236 ph = POP_ph();
237 push_str(argstr);
238 PUSH_ph(ph);
239 fword("interpose");
243 free( str );
244 RET( -1 );
247 /* ( block0 -- flag? ) */
248 static void
249 sunparts_probe( __attribute__((unused))sunparts_info_t *dummy )
251 unsigned char *buf = (unsigned char *)POP();
253 DPRINTF("probing for Sun partitions\n");
255 RET ( has_sun_part_magic(buf) );
258 /* ( -- type offset.d size.d ) */
259 static void
260 sunparts_get_info( sunparts_info_t *di )
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 );
270 static void
271 sunparts_block_size( __attribute__((unused))sunparts_info_t *di )
273 PUSH(512);
276 static void
277 sunparts_initialize( __attribute__((unused))sunparts_info_t *di )
279 fword("register-partition-package");
282 /* ( pos.d -- status ) */
283 static void
284 sunparts_seek(sunparts_info_t *di )
286 long long pos = DPOP();
287 long long offs, size;;
289 DPRINTF("sunparts_seek %llx:\n", pos);
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 );
296 /* Calculate the seek offset for the parent */
297 offs = ((ducell)di->offs_hi << BITS) | di->offs_lo;
298 offs += pos;
299 DPUSH(offs);
301 DPRINTF("sunparts_seek parent offset %llx:\n", offs);
303 call_package(di->seek_xt, my_parent());
306 /* ( buf len -- actlen ) */
307 static void
308 sunparts_read(sunparts_info_t *di )
310 DPRINTF("sunparts_read\n");
312 /* Pass the read back up to the parent */
313 call_package(di->read_xt, my_parent());
316 /* ( addr -- size ) */
317 static void
318 sunparts_load( __attribute__((unused))sunparts_info_t *di )
320 /* Invoke the loader */
321 load(my_self());
324 /* ( pathstr len -- ) */
325 static void
326 sunparts_dir( sunparts_info_t *di )
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();
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 },
354 void
355 sunparts_init( void )
357 REGISTER_NODE( sunparts );