ppc64: Don't set Kp bit on SLB
[openbios.git] / packages / disk-label.c
blob44b9f9ef03b2d3894dd75b78a8e16cdcf5f02c03
1 /*
2 * Creation Date: <2003/12/03 22:10:45 samuel>
3 * Time-stamp: <2004/01/07 19:17:45 samuel>
5 * <disk-label.c>
7 * 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
13 * version 2
17 #include "config.h"
18 #include "libopenbios/bindings.h"
19 #include "libopenbios/load.h"
20 #include "libc/diskio.h"
21 #include "libc/vsprintf.h"
22 #include "packages.h"
24 //#define DEBUG_DISK_LABEL
26 #ifdef DEBUG_DISK_LABEL
27 #define DPRINTF(fmt, args...) \
28 do { printk("DISK-LABEL - %s: " fmt, __func__ , ##args); } while (0)
29 #else
30 #define DPRINTF(fmt, args...) do { } while (0)
31 #endif
33 typedef struct {
34 xt_t parent_seek_xt;
35 xt_t parent_tell_xt;
36 xt_t parent_read_xt;
38 ucell offs_hi, offs_lo;
39 ucell size_hi, size_lo;
40 int block_size;
41 int type; /* partition type or -1 */
43 ihandle_t part_ih;
44 phandle_t filesystem_ph;
45 } dlabel_info_t;
47 DECLARE_NODE( dlabel, 0, sizeof(dlabel_info_t), "/packages/disk-label" );
50 /* ( -- ) */
51 static void
52 dlabel_close( __attribute__((unused))dlabel_info_t *di )
56 /* ( -- success? ) */
57 static void
58 dlabel_open( dlabel_info_t *di )
60 char *path;
61 char block0[512];
62 phandle_t ph;
63 int success=0;
64 cell status;
66 path = my_args_copy();
68 DPRINTF("dlabel-open '%s'\n", path );
70 di->part_ih = 0;
72 /* Find parent methods */
73 di->filesystem_ph = 0;
74 di->parent_seek_xt = find_parent_method("seek");
75 di->parent_tell_xt = find_parent_method("tell");
76 di->parent_read_xt = find_parent_method("read");
78 /* Read first block from parent device */
79 DPUSH(0);
80 call_package(di->parent_seek_xt, my_parent());
81 POP();
83 PUSH(pointer2cell(block0));
84 PUSH(sizeof(block0));
85 call_package(di->parent_read_xt, my_parent());
86 status = POP();
87 if (status != sizeof(block0))
88 goto out;
90 /* Find partition handler */
91 PUSH( pointer2cell(block0) );
92 selfword("find-part-handler");
93 ph = POP_ph();
94 if( ph ) {
95 /* We found a suitable partition handler, so interpose it */
96 DPRINTF("Partition found on disk - scheduling interpose with ph " FMT_ucellx "\n", ph);
98 push_str(path);
99 PUSH_ph(ph);
100 fword("interpose");
102 success = 1;
103 } else {
104 /* unknown (or missing) partition map,
105 * try the whole disk
108 DPRINTF("Unknown or missing partition map; trying whole disk\n");
110 /* Probe for filesystem from start of device */
111 DPUSH ( 0 );
112 PUSH_ih( my_self() );
113 selfword("find-filesystem");
114 ph = POP_ph();
115 if( ph ) {
116 /* If we have been asked to open a particular file, interpose the filesystem package with the passed filename as an argument */
117 di->filesystem_ph = ph;
119 DPRINTF("Located filesystem with ph " FMT_ucellx "\n", ph);
120 DPRINTF("path: %s length: %d\n", path, strlen(path));
122 if (path && strlen(path)) {
123 DPRINTF("INTERPOSE!\n");
125 push_str( path );
126 PUSH_ph( ph );
127 fword("interpose");
129 } else if (path && strcmp(path, "%BOOT") != 0) {
130 goto out;
133 success = 1;
136 out:
137 if( path )
138 free( path );
139 if( !success ) {
140 dlabel_close( di );
141 RET(0);
143 PUSH(-1);
146 /* ( addr len -- actual ) */
147 static void
148 dlabel_read( dlabel_info_t *di )
150 /* Call back up to parent */
151 call_package(di->parent_read_xt, my_parent());
154 /* ( pos.d -- status ) */
155 static void
156 dlabel_seek( dlabel_info_t *di )
158 /* Call back up to parent */
159 call_package(di->parent_seek_xt, my_parent());
162 /* ( -- filepos.d ) */
163 static void
164 dlabel_tell( dlabel_info_t *di )
166 /* Call back up to parent */
167 call_package(di->parent_tell_xt, my_parent());
170 /* ( addr len -- actual ) */
171 static void
172 dlabel_write( __attribute__((unused)) dlabel_info_t *di )
174 DDROP();
175 PUSH( -1 );
178 /* ( addr -- size ) */
179 static void
180 dlabel_load( __attribute__((unused)) dlabel_info_t *di )
182 /* Try the load method of the part package */
183 #ifdef DEBUG_DISK_LABEL
184 char *buf;
185 #endif
186 xt_t xt;
188 #ifdef DEBUG_DISK_LABEL
189 buf = (char *)POP();
190 #else
191 POP();
192 #endif
194 DPRINTF("load invoked with address %p\n", buf);
196 /* If we have a partition handle, invoke the load word on it */
197 if (di->part_ih) {
198 xt = find_ih_method("load", di->part_ih);
199 if (!xt) {
200 forth_printf("load currently not implemented for ihandle " FMT_ucellx "\n", di->part_ih);
201 PUSH(0);
202 return;
205 DPRINTF("calling load on ihandle " FMT_ucellx "\n", di->part_ih);
207 call_package(xt, di->part_ih);
208 } else {
209 /* Otherwise attempt load directly on the raw disk */
210 DPRINTF("calling load on raw disk ihandle " FMT_ucellx "\n", my_self());
212 load(my_self());
216 /* ( pathstr len -- ) */
217 static void
218 dlabel_dir( dlabel_info_t *di )
220 if ( di->filesystem_ph ) {
221 PUSH( my_self() );
222 push_str("dir");
223 PUSH( di->filesystem_ph );
224 fword("find-method");
225 POP();
226 fword("execute");
227 } else {
228 forth_printf("disk-label: Unable to determine filesystem\n");
229 POP();
230 POP();
234 NODE_METHODS( dlabel ) = {
235 { "open", dlabel_open },
236 { "close", dlabel_close },
237 { "load", dlabel_load },
238 { "read", dlabel_read },
239 { "write", dlabel_write },
240 { "seek", dlabel_seek },
241 { "tell", dlabel_tell },
242 { "dir", dlabel_dir },
245 void
246 disklabel_init( void )
248 REGISTER_NODE( dlabel );