Import of openhackware-0.4.1
[openhackware.git] / src / libpart / prep.c
blobb3bcdb9d82edecb7fa2f77a8bbbc38341c0ba622
1 /*
2 * <prep.c>
4 * Open Hack'Ware PREP BIOS partition type 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
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.
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
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include "bios.h"
25 #include "libpart.h"
27 /* PREP image management */
28 typedef struct MSDOS_part_t MSDOS_part_t;
29 struct MSDOS_part_t {
30 uint8_t boot_ind;
31 uint8_t start_head;
32 uint8_t start_sect;
33 uint8_t start_cyl;
34 uint8_t sys_ind;
35 uint8_t end_head;
36 uint8_t end_sect;
37 uint8_t end_cyl;
38 uint32_t LBA_start;
39 uint32_t LBA_end;
40 } __attribute__ ((packed));
42 part_t *PREP_find_partition (bloc_device_t *bd)
44 MSDOS_part_t *p;
45 part_t *part;
46 uint8_t *buffer;
47 uint32_t boot_offset, boot_size;
48 int i;
50 part = NULL;
51 buffer = malloc(0x200);
52 bd_seek(bd, 0, 0);
53 if (bd_read(bd, buffer, 0x200) < 0) {
54 ERROR("Unable to read boot sector from boot device. Aborting...\n");
55 goto error;
57 if (buffer[0x1FE] != 0x55 || buffer[0x1FF] != 0xAA) {
58 ERROR("No MSDOS signature (%x %x %x %x)\n",
59 buffer[0x000], buffer[0x001], buffer[0x1FE], buffer[0x1FF]);
60 goto error;
62 for (i = 0; i < 4; i++) {
63 p = (void *)(&buffer[0x1BE + (0x10 * i)]);
64 DPRINTF("partition %d: %x is %sbootable - ", i, p->boot_ind,
65 (p->boot_ind & 0x80) ? "" : "not ");
66 DPRINTF("start %0x end %0x type %x\n",
67 get_le32(&p->LBA_start), get_le32(&p->LBA_end), p->sys_ind);
68 #if 0
69 if (p->boot_ind != 0x80)
70 continue;
71 #endif
72 switch (p->sys_ind) {
73 case 0x07: /* HPFS/NTFS */
74 goto register_nonboot;
75 case 0x08: /* AIX */
76 goto register_nonboot;
77 case 0x09: /* AIX bootable */
78 /* Not supported by now */
79 break;
80 case 0x0A: /* OS/2 boot manager */
81 /* Not supported by now */
82 break;
83 case 0x41: /* PREP boot */
84 part = malloc(sizeof(part_t));
85 memset(part, 0, sizeof(part_t));
86 part->bd = bd;
87 part_set_blocsize(bd, part, 0x200);
88 /* Convert start and size into LBA */
89 if ((p->start_head != 0 || p->start_cyl != 0 ||
90 p->start_sect != 0) && p->LBA_start == 0) {
91 DPRINTF("start: use CHS\n");
92 part->start = bd_CHS2sect(bd, p->start_cyl,
93 p->start_head,
94 p->start_sect);
95 } else {
96 DPRINTF("start: use LBA\n");
97 part->start = get_le32(&p->LBA_start);
99 if ((p->end_head != 0 || p->end_cyl != 0 ||
100 p->end_sect != 0) && p->LBA_end == 0) {
101 DPRINTF("end: use CHS\n");
102 part->size = bd_CHS2sect(bd, p->end_cyl,
103 p->end_head, p->end_sect);
104 } else {
105 DPRINTF("end: use LBA\n");
106 part->size = get_le32(&p->LBA_end);
108 /* XXX: seems that some (AIX !)
109 * code the size here instead of partition end
111 if (part->size > part->start)
112 part->size -= part->start;
113 DPRINTF("LBA: start %0x size: %0x\n", part->start, part->size);
114 /* Now, find and check boot record */
115 part_seek(part, 0, 0);
116 if (bd_read(bd, buffer, part->bloc_size) < 0) {
117 ERROR("%s sector_read failed (%d)\n", __func__, i);
118 freep(&part);
119 goto error;
121 #if 0
122 if (buffer[0x1FE] != 0x55 || buffer[0x1FF] != 0xAA) {
123 ERROR("No MSDOS signature on PREP boot record\n");
124 freep(&part);
125 goto error;
127 #endif
128 boot_offset = get_le32(buffer);
129 boot_size = get_le32(buffer + 4);
130 if ((boot_offset & 3) || /*(boot_size & 3) ||*/
131 boot_offset == 0 || boot_size == 0) {
132 DPRINTF("Suspicious PREP boot parameters: %08x %08x %08x %08x\n",
133 part->start, part->start * 0x200, boot_offset, boot_size);
134 #if 0
135 freep(&part);
136 goto error;
137 #else
138 /* IBM boot blocs respect the norm better than others... */
139 part->start++;
140 part_seek(part, 0, 0);
141 if (bd_read(bd, buffer, part->bloc_size) < 0) {
142 ERROR("%s sector_read failed (%d)\n", __func__, i);
143 freep(&part);
144 goto error;
146 boot_offset = get_le32(buffer);
147 boot_size = get_le32(buffer + 4);
148 #endif
150 DPRINTF("PREP boot parameters: %08x %08x %08x %08x\n",
151 part->start, part->start * 0x200, boot_offset, boot_size);
152 if (boot_size > (part->size * part->bloc_size)) {
153 ERROR("PREP boot image greater than boot partition: %0x %0x\n",
154 boot_size, part->size * part->bloc_size);
155 #if 0
156 freep(&part);
157 goto error;
158 #endif
160 part->boot_start.bloc = 0;
161 part->boot_start.offset = 0;
162 part->boot_size.bloc = boot_size / part->bloc_size;
163 part->boot_size.offset = boot_size % part->bloc_size;
164 part->boot_load = 0;
165 part->boot_entry = boot_offset - part->bloc_size;
166 part->flags = PART_TYPE_PREP | PART_FLAG_BOOT;
167 part_register(bd, part, "PREP boot");
168 fs_raw_set_bootfile(part, part->boot_start.bloc,
169 part->boot_start.offset,
170 part->boot_size.bloc,
171 part->boot_size.offset);
172 break;
173 case 0x63: /* GNU Hurd */
174 goto register_nonboot;
175 case 0x83: /* Linux */
176 goto register_nonboot;
177 case 86 ... 87: /* NFTS volume set */
178 /* Not supported by now */
179 break;
180 case 0x8E: /* Linux LVM */
181 /* Not supported by now */
182 break;
183 case 0x96: /* AIX seems to use this to identify ISO 9660 'partitions' */
184 break;
185 case 0xA5: /* FreeBSD */
186 goto register_nonboot;
187 case 0xA6: /* OpenBSD */
188 goto register_nonboot;
189 case 0xA7: /* NeXTSTEP */
190 goto register_nonboot;
191 case 0xA8: /* Darwin UFS */
192 goto register_nonboot;
193 case 0xA9: /* NetBSD */
194 goto register_nonboot;
195 case 0xAB: /* Darwin boot */
196 /* Not supported by now */
197 break;
198 case 0xBE: /* Solaris boot */
199 /* Not supported by now */
200 break;
201 case 0xEB: /* BeOS fs */
202 goto register_nonboot;
203 case 0xFD: /* Linux RAID */
204 /* Not supported by now */
205 break;
206 default:
207 break;
208 register_nonboot:
209 break;
212 error:
213 free(buffer);
215 return part;