Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openhackware / src / libpart / core.c
1 /*
2  * <part.c>
3  *
4  * Open Hack'Ware BIOS partitions management
5  * 
6  * Copyright (c) 2004-2005 Jocelyn Mayer
7  * 
8  *   This program is free software; you can redistribute it and/or
9  *   modify it under the terms of the GNU General Public License V2
10  *   as published by the Free Software Foundation
11  *
12  *   This program is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with this program; if not, write to the Free Software
19  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include "bios.h"
25 #include "libpart.h"
26
27 /* Bootable partitions detection and management */
28 part_t *part_open (bloc_device_t *bd,
29                    uint32_t start, uint32_t size, uint32_t spb)
30 {
31     part_t *part;
32
33     if (bd_seek(bd, (start + size) * spb, 0) < 0)
34         return NULL;
35     part = malloc(sizeof(part_t));
36     if (part == NULL)
37         return NULL;
38     part->bd = bd;
39     part->start = start;
40     part->size = size;
41     part->spb = spb;
42
43     return part;
44 }
45
46 int part_seek (part_t *part, uint32_t bloc, uint32_t pos)
47 {
48     if (bloc > part->size) {
49         ERROR("bloc: %d part size: %d %p\n", bloc, part->size, part);
50         return -1;
51     }
52     bloc += part->start;
53     if (part->spb != 0) {
54         bloc *= part->spb;
55         pos = pos % part->bloc_size;
56     } else {
57         pos += (bloc % part->bps) * part->bloc_size;
58         bloc /= part->bps;
59     }
60
61     return bd_seek(part->bd, bloc, pos);
62 }
63
64 int part_read (part_t *part, void *buffer, int len)
65 {
66     return bd_read(part->bd, buffer, len);
67 }
68
69 int part_write (part_t *part, const void *buffer, int len)
70 {
71     return bd_write(part->bd, buffer, len);
72 }
73
74 void part_close (part_t *part)
75 {
76     part->size = 0;
77 }
78
79 uint32_t part_blocsize (part_t *part)
80 {
81     return part->bloc_size;
82 }
83
84 uint32_t part_flags (part_t *part)
85 {
86     return part->flags;
87 }
88
89 uint32_t part_size (part_t *part)
90 {
91     return part->size;
92 }
93
94 fs_t *part_fs (part_t *part)
95 {
96     return part->fs;
97 }
98
99 void part_private_set (part_t *part, void *private)
100 {
101     part->private = private;
102 }
103
104 void *part_private_get (part_t *part)
105 {
106     return part->private;
107 }
108
109 void part_set_blocsize (bloc_device_t *bd, part_t *part, uint32_t blocsize)
110 {
111     uint32_t seclen;
112
113     part->bloc_size = blocsize;
114     seclen = bd_seclen(bd);
115     if (blocsize < seclen) {
116         part->spb = 0;
117         part->bps = bd_seclen(bd) / part->bloc_size;
118         DPRINTF("%d part blocs in one sector (%d %d)\n", part->bps,
119                 part->bloc_size, bd_seclen(bd));
120     } else {
121         part->spb = part->bloc_size / bd_seclen(bd);
122         part->bps = 0;
123         DPRINTF("%d sectors in one part bloc (%d %d)\n", part->spb,
124                 part->bloc_size, bd_seclen(bd));
125     }
126 }
127
128 int part_register (bloc_device_t *bd, part_t *partition,
129                    const unsigned char *name, int partnum)
130 {
131     part_t **cur;
132
133     DPRINTF("Register partition '%s'\n", name);
134     partition->bd = bd;
135     partition->next = NULL;
136     partition->name = strdup(name);
137     partition->partnum = partnum;
138     for (cur = _bd_parts(bd); *cur != NULL; cur = &(*cur)->next)
139         continue;
140     *cur = partition;
141
142     return 0;
143 }
144
145 part_t *part_get (bloc_device_t *bd, int partnum)
146 {
147     part_t **listp, *cur;
148
149     listp = _bd_parts(bd);
150     
151     for (cur = *listp; cur != NULL; cur = cur->next) {
152         if (cur->partnum == partnum)
153             break;
154     }
155     
156     return cur;
157 }
158
159 part_t *part_get_raw (bloc_device_t *bd)
160 {
161     part_t *part;
162     uint32_t seclen;
163
164     part = malloc(sizeof(part_t));
165     part->start = 0;
166     seclen = bd_seclen(bd);
167     part->size = bd_maxbloc(bd);
168     if (seclen > 512) {
169         part->size *= seclen / 512;
170     } else {
171         part->size *= 512 / seclen;
172     }
173     part->boot_start.bloc = 0;
174     part->boot_start.offset = 0;
175     part->boot_size.bloc = part->size;
176     part->boot_size.offset = 0;
177     part->boot_load = 0;
178     part->boot_entry = 0;
179     part_set_blocsize(bd, part, 512);
180     part->bd = bd;
181     part->flags = PART_TYPE_RAW | PART_FLAG_BOOT;
182     part_register(bd, part, "Raw", 0);
183
184     return part;
185 }
186
187 bloc_device_t *part_get_bd (part_t *part)
188 {
189     return part->bd;
190 }
191
192 part_t *part_probe (bloc_device_t *bd, int set_raw)
193 {
194     part_t *part0 = NULL, *boot_part, **cur;
195
196     /* Try to find a valid boot partition */
197     boot_part = Apple_probe_partitions(bd);
198     if (boot_part == NULL) {
199         boot_part = isofs_probe_partitions(bd);
200         if (boot_part == NULL && arch == ARCH_PREP)
201             boot_part = PREP_find_partition(bd);
202         if (boot_part == NULL && set_raw != 0) {
203             dprintf("Use bloc device as raw partition\n");
204         }
205     }
206     if (_bd_parts(bd) == NULL) {
207         /* Register the 0 partition: raw partition containing the whole disk */
208         part0 = part_get_raw(bd);
209     }
210     /* Probe filesystem on each found partition */
211     for (cur = _bd_parts(bd); *cur != NULL; cur = &(*cur)->next) {
212         const unsigned char *map, *type;
213         switch ((*cur)->flags & 0x0F) {
214         case PART_TYPE_PREP:
215             map = "PREP";
216             break;
217         case PART_TYPE_APPLE:
218             map = "Apple";
219             break;
220         case PART_TYPE_ISO9660:
221             map = "ISO9660";
222             break;
223         default:
224             map = "Raw";
225             break;
226         }
227         switch ((*cur)->flags & 0xF0) {
228         case PART_FLAG_DUMMY:
229             type = "dummy";
230             break;
231         case PART_FLAG_DRIVER:
232             type = "driver";
233             break;
234         case PART_FLAG_PATCH:
235             type = "patches";
236             break;
237         case PART_FLAG_FS:
238             type = "filesystem";
239             break;
240         default:
241             type = "unknown";
242             break;
243         }
244         dprintf("Probe filesystem on %s %s partition '%s' %s %p\n",
245                 type, map, (*cur)->name,
246                 ((*cur)->flags) & PART_FLAG_BOOT ? "(bootable)" : "", *cur);
247         if (((*cur)->flags) & PART_FLAG_FS) {
248             if (((*cur)->flags) & PART_FLAG_BOOT)
249                 (*cur)->fs = fs_probe(*cur, 1);
250             else
251                 (*cur)->fs = fs_probe(*cur, 0);
252         } else if (((*cur)->flags) & PART_TYPE_RAW) {
253             (*cur)->fs = fs_probe(*cur, 2);
254         } else {
255             (*cur)->fs = fs_probe(*cur, 2);
256         }
257             fs_get_bootfile((*cur)->fs);
258         if (((*cur)->flags) & PART_FLAG_BOOT) {
259             dprintf("Partition is bootable (%d)\n", (*cur)->partnum);
260             bd_set_boot_part(bd, *cur, (*cur)->partnum);
261             if (boot_part == NULL)
262                 boot_part = *cur;
263         }
264     }
265     dprintf("Boot partition: %p %p %p %p\n", boot_part, boot_part->fs,
266             part_fs(boot_part), part0);
267
268     return boot_part;
269 }
270
271 int part_set_boot_file (part_t *part, uint32_t start, uint32_t offset,
272                         uint32_t size)
273 {
274     part->boot_start.bloc = start;
275     part->boot_start.offset = offset;
276     part->boot_size.bloc = size;
277     part->boot_size.offset = 0;
278     part->boot_load = 0;
279     part->boot_entry = 0;
280     part->flags |= PART_FLAG_BOOT;
281
282     return 0;
283 }
284
285 unsigned int part_get_entry (part_t *part)
286 {
287     return part->boot_entry;
288 }