2 * Creation Date: <2003/12/04 17:07:05 samuel>
3 * Time-stamp: <2004/01/07 19:36:09 samuel>
7 * macintosh partition support
9 * Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
18 #include "libopenbios/bindings.h"
19 #include "libopenbios/load.h"
20 #include "mac-parts.h"
21 #include "libc/byteorder.h"
22 #include "libc/vsprintf.h"
25 //#define CONFIG_DEBUG_MAC_PARTS
27 #ifdef CONFIG_DEBUG_MAC_PARTS
28 #define DPRINTF(fmt, args...) \
29 do { printk("MAC-PARTS: " fmt , ##args); } while (0)
31 #define DPRINTF(fmt, args...) do {} while(0)
35 xt_t seek_xt
, read_xt
;
36 ucell offs_hi
, offs_lo
;
37 ucell size_hi
, size_lo
;
38 unsigned int blocksize
;
39 phandle_t filesystem_ph
;
42 DECLARE_NODE( macparts
, INSTALL_OPEN
, sizeof(macparts_info_t
), "+/packages/mac-parts" );
44 #define SEEK( pos ) ({ DPUSH(pos); call_parent(di->seek_xt); POP(); })
45 #define READ( buf, size ) ({ PUSH(pointer2cell(buf)); PUSH(size); call_parent(di->read_xt); POP(); })
47 /* ( open -- flag ) */
49 macparts_open( macparts_info_t
*di
)
51 char *str
= my_args_copy();
52 char *argstr
= strdup("");
53 char *parstr
= strdup("");
58 int want_bootcode
= 0;
60 ducell offs
= 0, size
= -1;
62 DPRINTF("macparts_open '%s'\n", str
);
65 Arguments that we accept:
74 /* Detect the boot parameters */
79 if (*ptr
>= '0' && *ptr
<= '9' && *(ptr
+ 1) == ',') {
86 else if (*ptr
>= '0' && *ptr
<='9' && *(ptr
+ 1) == '\0') {
91 else if (*ptr
== ',') {
100 /* Convert the id to a partition number */
102 parnum
= atol(parstr
);
104 /* Detect if we are looking for the bootcode */
105 if (strcmp(argstr
, "%BOOT") == 0)
110 DPRINTF("parstr: %s argstr: %s parnum: %d\n", parstr
, argstr
, parnum
);
112 DPRINTF("want_bootcode %d\n", want_bootcode
);
113 DPRINTF("macparts_open %d\n", parnum
);
115 di
->filesystem_ph
= 0;
116 di
->read_xt
= find_parent_method("read");
117 di
->seek_xt
= find_parent_method("seek");
120 if( READ(&dmap
, sizeof(dmap
)) != sizeof(dmap
) )
123 /* partition maps might support multiple block sizes; in this case,
124 * pmPyPartStart is typically given in terms of 512 byte blocks.
126 bs
= __be16_to_cpu(dmap
.sbBlockSize
);
129 READ( &par
, sizeof(par
) );
130 if( __be16_to_cpu(par
.pmSig
) == DESC_PART_SIGNATURE
)
134 if( READ(&par
, sizeof(par
)) != sizeof(par
) )
136 if (__be16_to_cpu(par
.pmSig
) != DESC_PART_SIGNATURE
)
140 * Implement partition selection as per the PowerPC Microprocessor CHRP bindings
143 if (str
== NULL
|| parnum
== 0) {
144 /* According to the spec, partition 0 as well as no arguments means the whole disk */
146 size
= (long long)__be32_to_cpu(dmap
.sbBlkCount
) * bs
;
148 di
->blocksize
= (unsigned int)bs
;
150 di
->offs_hi
= offs
>> BITS
;
151 di
->offs_lo
= offs
& (ucell
) -1;
153 di
->size_hi
= size
>> BITS
;
154 di
->size_lo
= size
& (ucell
) -1;
159 } else if (parnum
== -1 && strlen(argstr
)) {
161 DPRINTF("mac-parts: counted %d partitions\n", __be32_to_cpu(par
.pmMapBlkCnt
));
163 /* No partition was explicitly requested, but an argstr was passed in.
164 So let's find a suitable partition... */
165 for (parnum
= 1; parnum
<= __be32_to_cpu(par
.pmMapBlkCnt
); parnum
++) {
167 READ( &par
, sizeof(par
) );
168 if( __be16_to_cpu(par
.pmSig
) != DESC_PART_SIGNATURE
||
169 !__be32_to_cpu(par
.pmPartBlkCnt
) )
172 DPRINTF("found partition type: %s with status %x\n", par
.pmPartType
, __be32_to_cpu(par
.pmPartStatus
));
174 /* If we have a valid, allocated and readable partition... */
175 if( (__be32_to_cpu(par
.pmPartStatus
) & kPartitionAUXIsValid
) &&
176 (__be32_to_cpu(par
.pmPartStatus
) & kPartitionAUXIsAllocated
) &&
177 (__be32_to_cpu(par
.pmPartStatus
) & kPartitionAUXIsReadable
) ) {
178 offs
= (long long)__be32_to_cpu(par
.pmPyPartStart
) * bs
;
179 size
= (long long)__be32_to_cpu(par
.pmPartBlkCnt
) * bs
;
181 /* If the filename was set to %BOOT, we actually want the bootcode */
182 if (want_bootcode
&& (__be32_to_cpu(par
.pmPartStatus
) & kPartitionAUXIsBootValid
)) {
183 offs
+= (long long)__be32_to_cpu(par
.pmLgBootStart
) * bs
;
184 size
= (long long)__be32_to_cpu(par
.pmBootSize
);
188 /* Otherwise we were passed a filename and path. So let's
189 choose the first partition with a valid filesystem */
191 PUSH_ih( my_parent() );
192 parword("find-filesystem");
202 /* Another partition was explicitly requested */
204 READ( &par
, sizeof(par
) );
206 if( (__be32_to_cpu(par
.pmPartStatus
) & kPartitionAUXIsValid
) &&
207 (__be32_to_cpu(par
.pmPartStatus
) & kPartitionAUXIsAllocated
) &&
208 (__be32_to_cpu(par
.pmPartStatus
) & kPartitionAUXIsReadable
) ) {
210 offs
= (long long)__be32_to_cpu(par
.pmPyPartStart
) * bs
;
211 size
= (long long)__be32_to_cpu(par
.pmPartBlkCnt
) * bs
;
215 /* If we couldn't find a partition, exit */
217 DPRINTF("Unable to automatically find partition!\n");
224 di
->blocksize
= (unsigned int)bs
;
226 di
->offs_hi
= offs
>> BITS
;
227 di
->offs_lo
= offs
& (ucell
) -1;
229 di
->size_hi
= size
>> BITS
;
230 di
->size_lo
= size
& (ucell
) -1;
232 /* We have a valid partition - so probe for a filesystem at the current offset */
233 DPRINTF("mac-parts: about to probe for fs\n");
235 PUSH_ih( my_parent() );
236 parword("find-filesystem");
237 DPRINTF("mac-parts: done fs probe\n");
241 DPRINTF("mac-parts: filesystem found with ph " FMT_ucellx
" and args %s\n", ph
, argstr
);
242 di
->filesystem_ph
= ph
;
244 /* If the filename was %BOOT then it's not a real filename, so clear argstr before
245 attempting interpose */
249 /* If we have been asked to open a particular file, interpose the filesystem package with
250 the passed filename as an argument */
251 if (strlen(argstr
)) {
257 DPRINTF("mac-parts: no filesystem found; bypassing misc-files interpose\n");
266 /* ( block0 -- flag? ) */
268 macparts_probe( macparts_info_t
*dummy
)
270 desc_map_t
*dmap
= (desc_map_t
*)cell2pointer(POP());
272 DPRINTF("macparts_probe %x ?= %x\n", dmap
->sbSig
, DESC_MAP_SIGNATURE
);
273 if( __be16_to_cpu(dmap
->sbSig
) != DESC_MAP_SIGNATURE
)
278 /* ( -- type offset.d size.d ) */
280 macparts_get_info( macparts_info_t
*di
)
282 DPRINTF("macparts_get_info");
284 PUSH( -1 ); /* no type */
292 macparts_block_size( macparts_info_t
*di
)
294 DPRINTF("macparts_block_size = %x\n", di
->blocksize
);
299 macparts_initialize( macparts_info_t
*di
)
301 fword("register-partition-package");
304 /* ( pos.d -- status ) */
306 macparts_seek(macparts_info_t
*di
)
308 long long pos
= DPOP();
309 long long offs
, size
;
311 DPRINTF("macparts_seek %llx:\n", pos
);
313 /* Seek is invalid if we reach the end of the device */
314 size
= ((ducell
)di
->size_hi
<< BITS
) | di
->size_lo
;
318 /* Calculate the seek offset for the parent */
319 offs
= ((ducell
)di
->offs_hi
<< BITS
) | di
->offs_lo
;
323 DPRINTF("macparts_seek parent offset %llx:\n", offs
);
325 call_package(di
->seek_xt
, my_parent());
328 /* ( buf len -- actlen ) */
330 macparts_read(macparts_info_t
*di
)
332 DPRINTF("macparts_read\n");
334 /* Pass the read back up to the parent */
335 call_package(di
->read_xt
, my_parent());
338 /* ( addr -- size ) */
340 macparts_load( __attribute__((unused
))macparts_info_t
*di
)
342 /* Invoke the loader */
346 /* ( pathstr len -- ) */
348 macparts_dir( macparts_info_t
*di
)
350 /* On PPC Mac, the first partition chosen according to the CHRP boot
351 specification (i.e. marked as bootable) may not necessarily contain
353 if ( di
->filesystem_ph
) {
356 PUSH( di
->filesystem_ph
);
357 fword("find-method");
361 forth_printf("mac-parts: Unable to determine filesystem\n");
367 NODE_METHODS( macparts
) = {
368 { "probe", macparts_probe
},
369 { "open", macparts_open
},
370 { "seek", macparts_seek
},
371 { "read", macparts_read
},
372 { "load", macparts_load
},
373 { "dir", macparts_dir
},
374 { "get-info", macparts_get_info
},
375 { "block-size", macparts_block_size
},
376 { NULL
, macparts_initialize
},
380 macparts_init( void )
382 REGISTER_NODE( macparts
);