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
16 #include "libopenbios/bindings.h"
17 #include "libopenbios/load.h"
18 #include "libc/byteorder.h"
19 #include "libc/vsprintf.h"
22 //#define DEBUG_SUN_PARTS
24 #ifdef DEBUG_SUN_PARTS
25 #define DPRINTF(fmt, args...) \
26 do { printk(fmt , ##args); } while (0)
28 #define DPRINTF(fmt, args...)
32 xt_t seek_xt
, read_xt
;
33 ucell offs_hi
, offs_lo
;
34 ucell size_hi
, size_lo
;
36 phandle_t filesystem_ph
;
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 */
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
;
69 uint16_t magic
; /* Magic number */
70 uint16_t csum
; /* Label xor'd checksum */
73 /* two helper functions */
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)
85 for (ush
= (uint16_t *)p
; ush
< (uint16_t *)(p
+ 1); ush
++) {
86 tmp16
= __be16_to_cpu(*ush
);
92 /* ( open -- flag ) */
94 sunparts_open( sunparts_info_t
*di
)
96 char *str
= my_args_copy();
97 char *argstr
= strdup("");
98 char *parstr
= strdup("");
100 unsigned char buf
[512];
101 struct sun_disklabel
*p
;
106 DPRINTF("sunparts_open '%s'\n", str
);
109 Arguments that we accept:
118 /* Detect the boot parameters */
123 if (((*ptr
>= '0' && *ptr
<= '9') || (*ptr
>= 'a' && *ptr
<= 'a' + 8)) && *(ptr
+ 1) == ',') {
130 else if (((*ptr
>= '0' && *ptr
<= '9') || (*ptr
>= 'a' && *ptr
<= 'a' + 8)) && *(ptr
+ 1) == '\0') {
135 else if (*ptr
== ',') {
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';
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");
161 if( READ(buf
, 512) != 512 )
165 if (!has_sun_part_magic(buf
)) {
166 DPRINTF("Sun partition magic not found.\n");
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
);
178 if (p
->partitions
[i
].num_sectors
!= 0 && p
->infos
[i
].id
!= 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");
204 PUSH_ih( my_parent() );
205 parword("find-filesystem");
206 DPRINTF("sun-parts: done fs probe\n");
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
)) {
221 DPRINTF("sun-parts: no filesystem found; bypassing misc-files interpose\n");
228 /* ( block0 -- flag? ) */
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 ) */
241 sunparts_get_info( sunparts_info_t
*di
)
243 DPRINTF("Sun get_info\n");
252 sunparts_block_size( __attribute__((unused
))sunparts_info_t
*di
)
258 sunparts_initialize( __attribute__((unused
))sunparts_info_t
*di
)
260 fword("register-partition-package");
263 /* ( pos.d -- status ) */
265 sunparts_seek(sunparts_info_t
*di
)
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
;
277 DPRINTF("sunparts_seek parent offset %llx:\n", offs
);
279 call_package(di
->seek_xt
, my_parent());
282 /* ( buf len -- actlen ) */
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 ) */
294 sunparts_load( __attribute__((unused
))sunparts_info_t
*di
)
296 /* Invoke the loader */
300 /* ( pathstr len -- ) */
302 sunparts_dir( sunparts_info_t
*di
)
304 if ( di
->filesystem_ph
) {
307 PUSH( di
->filesystem_ph
);
308 fword("find-method");
312 forth_printf("sun-parts: Unable to determine filesystem\n");
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
},
331 sunparts_init( void )
333 REGISTER_NODE( sunparts
);