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 */
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
;
67 uint16_t magic
; /* Magic number */
68 uint16_t csum
; /* Label xor'd checksum */
71 /* two helper functions */
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)
83 for (ush
= (uint16_t *)p
; ush
< (uint16_t *)(p
+ 1); ush
++) {
84 tmp16
= __be16_to_cpu(*ush
);
90 /* ( open -- flag ) */
92 sunparts_open( sunparts_info_t
*di
)
94 char *str
= my_args_copy();
98 unsigned char buf
[512];
99 struct sun_disklabel
*p
;
104 DPRINTF("sunparts_open '%s'\n", str
);
107 Arguments that we accept:
116 /* Detect the boot parameters */
121 if (((*ptr
>= '0' && *ptr
<= '9') || (*ptr
>= 'a' && *ptr
<= 'a' + 8)) && *(ptr
+ 1) == ',') {
128 else if (((*ptr
>= '0' && *ptr
<= '9') || (*ptr
>= 'a' && *ptr
<= 'a' + 8)) && *(ptr
+ 1) == '\0') {
133 else if (*ptr
== ',') {
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';
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");
159 if (READ(buf
, 512) != 512) {
165 if (!has_sun_part_magic(buf
)) {
166 DPRINTF("Sun partition magic not found.\n");
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
));
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
;
195 DPRINTF("Partition size is 0, exiting\n");
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");
209 PUSH_ih( my_parent() );
210 parword("find-filesystem");
211 DPRINTF("sun-parts: done fs probe\n");
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
)) {
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");
247 /* ( block0 -- flag? ) */
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 ) */
260 sunparts_get_info( sunparts_info_t
*di
)
262 DPRINTF("Sun get_info\n");
271 sunparts_block_size( __attribute__((unused
))sunparts_info_t
*di
)
277 sunparts_initialize( __attribute__((unused
))sunparts_info_t
*di
)
279 fword("register-partition-package");
282 /* ( pos.d -- status ) */
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
;
296 /* Calculate the seek offset for the parent */
297 offs
= ((ducell
)di
->offs_hi
<< BITS
) | di
->offs_lo
;
301 DPRINTF("sunparts_seek parent offset %llx:\n", offs
);
303 call_package(di
->seek_xt
, my_parent());
306 /* ( buf len -- actlen ) */
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 ) */
318 sunparts_load( __attribute__((unused
))sunparts_info_t
*di
)
320 /* Invoke the loader */
324 /* ( pathstr len -- ) */
326 sunparts_dir( sunparts_info_t
*di
)
328 if ( di
->filesystem_ph
) {
331 PUSH( di
->filesystem_ph
);
332 fword("find-method");
336 forth_printf("sun-parts: Unable to determine filesystem\n");
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
},
355 sunparts_init( void )
357 REGISTER_NODE( sunparts
);