md.c revision 1.2 1 /* $NetBSD: md.c,v 1.2 2014/08/03 16:09:39 martin Exp $ */
2
3 /*
4 * Copyright 1997 Piermont Information Systems Inc.
5 * All rights reserved.
6 *
7 * Based on code written by Philip A. Nelson for Piermont Information
8 * Systems Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. The name of Piermont Information Systems Inc. may not be used to endorse
19 * or promote products derived from this software without specific prior
20 * written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
26 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32 * THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 /* md.c -- arc machine specific routines */
36
37 #include <sys/param.h>
38 #include <sys/sysctl.h>
39 #include <stdio.h>
40 #include <util.h>
41 #include <machine/cpu.h>
42
43 #include "defs.h"
44 #include "md.h"
45 #include "msg_defs.h"
46 #include "menu_defs.h"
47
48 /*
49 * ARC BIOS reognizes only FAT, so we have to have a FAT partition
50 * to store our native bootloader.
51 */
52 static int nobootfs = 0;
53 static int bootpart_fat12 = PART_BOOT_FAT12;
54
55 void
56 md_init(void)
57 {
58 }
59
60 void
61 md_init_set_status(int flags)
62 {
63 (void)flags;
64 }
65
66 int
67 md_get_info(void)
68 {
69 return set_bios_geom_with_mbr_guess();
70 }
71
72 /*
73 * md back-end code for menu-driven BSD disklabel editor.
74 */
75 int
76 md_make_bsd_partitions(void)
77 {
78 int i;
79 int part;
80 int maxpart = getmaxpartitions();
81 int partstart;
82 int part_raw, part_bsd;
83 int ptend;
84 int no_swap = 0;
85 partinfo *p;
86
87 /*
88 * Initialize global variables that track space used on this disk.
89 * Standard 4.4BSD 8-partition labels always cover whole disk.
90 */
91 if (pm->ptsize == 0)
92 pm->ptsize = pm->dlsize - pm->ptstart;
93 if (pm->dlsize == 0)
94 pm->dlsize = pm->ptstart + pm->ptsize;
95
96 partstart = pm->ptstart;
97 ptend = pm->ptstart + pm->ptsize;
98
99 /* Ask for layout type -- standard or special */
100 msg_display(MSG_layout,
101 pm->ptsize / (MEG / pm->sectorsize),
102 DEFROOTSIZE + DEFSWAPSIZE + DEFUSRSIZE,
103 DEFROOTSIZE + DEFSWAPSIZE + DEFUSRSIZE + XNEEDMB);
104
105 process_menu(MENU_layout, NULL);
106
107 /* Set so we use the 'real' geometry for rounding, input in MB */
108 pm->current_cylsize = pm->dlcylsize;
109 set_sizemultname_meg();
110
111 /* Build standard partitions */
112 memset(&pm->bsdlabel, 0, sizeof pm->bsdlabel);
113
114 /* Set initial partition types to unused */
115 for (part = 0 ; part < maxpart ; ++part)
116 pm->bsdlabel[part].pi_fstype = FS_UNUSED;
117
118 /* Whole disk partition */
119 part_raw = getrawpartition();
120 if (part_raw == -1)
121 part_raw = PART_C; /* for sanity... */
122 pm->bsdlabel[part_raw].pi_offset = 0;
123 pm->bsdlabel[part_raw].pi_size = pm->dlsize;
124
125 if (part_raw == PART_D) {
126 /* Probably a system that expects an i386 style mbr */
127 part_bsd = PART_C;
128 pm->bsdlabel[PART_C].pi_offset = pm->ptstart;
129 pm->bsdlabel[PART_C].pi_size = pm->ptsize;
130 } else {
131 part_bsd = part_raw;
132 }
133
134 if (pm->bootsize != 0) {
135 pm->bsdlabel[PART_BOOT_FAT12].pi_fstype = FS_MSDOS;
136 pm->bsdlabel[PART_BOOT_FAT12].pi_size = pm->bootsize;
137 pm->bsdlabel[PART_BOOT_FAT12].pi_offset = pm->bootstart;
138 pm->bsdlabel[PART_BOOT_FAT12].pi_flags |= PART_BOOT_FAT12_PI_FLAGS;
139 strlcpy(pm->bsdlabel[PART_BOOT_FAT12].pi_mount,
140 PART_BOOT_FAT12_PI_MOUNT,
141 sizeof pm->bsdlabel[PART_BOOT_FAT12].pi_mount);
142 }
143
144 #ifdef PART_REST
145 pm->bsdlabel[PART_REST].pi_offset = 0;
146 pm->bsdlabel[PART_REST].pi_size = pm->ptstart;
147 #endif
148
149 /*
150 * Save any partitions that are outside the area we are
151 * going to use.
152 * In particular this saves details of the other MBR
153 * partitions on a multiboot i386 system.
154 */
155 for (i = maxpart; i--;) {
156 if (pm->bsdlabel[i].pi_size != 0)
157 /* Don't overwrite special partitions */
158 continue;
159 p = &pm->oldlabel[i];
160 if (p->pi_fstype == FS_UNUSED || p->pi_size == 0)
161 continue;
162 if (layoutkind == LY_USEEXIST) {
163 if (PI_ISBSDFS(p))
164 p->pi_flags |= PIF_MOUNT;
165 } else {
166 if (p->pi_offset < pm->ptstart + pm->ptsize &&
167 p->pi_offset + p->pi_size > pm->ptstart)
168 /* Not outside area we are allocating */
169 continue;
170 if (p->pi_fstype == FS_SWAP)
171 no_swap = 1;
172 }
173 pm->bsdlabel[i] = pm->oldlabel[i];
174 }
175
176 if (layoutkind == LY_USEEXIST) {
177 /* XXX Check we have a sensible layout */
178 ;
179 } else
180 get_ptn_sizes(partstart, ptend - partstart, no_swap);
181
182 /*
183 * OK, we have a partition table. Give the user the chance to
184 * edit it and verify it's OK, or abort altogether.
185 */
186 edit_check:
187 if (edit_and_check_label(pm->bsdlabel, maxpart, part_raw, part_bsd) == 0) {
188 msg_display(MSG_abort);
189 return 0;
190 }
191 if (md_check_partitions() == 0)
192 goto edit_check;
193
194 /* Disk name */
195 msg_prompt(MSG_packname, pm->bsddiskname, pm->bsddiskname, sizeof pm->bsddiskname);
196
197 /* save label to disk for MI code to update. */
198 (void)savenewlabel(pm->bsdlabel, maxpart);
199
200 /* Everything looks OK. */
201 return 1;
202 }
203
204 /*
205 * any additional partition validation
206 */
207 int
208 md_check_partitions(void)
209 {
210 int part;
211
212 /* we need to find a boot partition, otherwise we can't write our
213 * bootloader. We make the assumption that the user hasn't done
214 * something stupid, like move it away from the MBR partition.
215 */
216 for (part = PART_A; part < MAXPARTITIONS; part++)
217 if (pm->bsdlabel[part].pi_fstype == FS_MSDOS) {
218 bootpart_fat12 = part;
219 return 1;
220 }
221
222 msg_display(MSG_nobootpartdisklabel);
223 process_menu(MENU_ok, NULL);
224 return 0;
225 }
226
227 /*
228 * hook called before writing new disklabel.
229 */
230 int
231 md_pre_disklabel(void)
232 {
233 msg_display(MSG_dofdisk);
234
235 /* write edited MBR onto disk. */
236 if (write_mbr(pm->diskdev, &mbr, 1) != 0) {
237 msg_display(MSG_wmbrfail);
238 process_menu(MENU_ok, NULL);
239 return 1;
240 }
241 return 0;
242 }
243
244 /*
245 * hook called after writing disklabel to new target disk.
246 */
247 int
248 md_post_disklabel(void)
249 {
250 if (get_ramsize() <= 32)
251 set_swap(pm->diskdev, pm->bsdlabel);
252 return 0;
253 }
254
255 /*
256 * hook called after upgrade() or install() has finished setting
257 * up the target disk but immediately before the user is given the
258 * ``disks are now set up'' message.
259 */
260 int
261 md_post_newfs(void)
262 {
263 if (!nobootfs) {
264 msg_display(msg_string(MSG_copybootloader), pm->diskdev);
265 cp_to_target("/usr/mdec/boot", PART_BOOT_FAT12_PI_MOUNT);
266 }
267
268 return 0;
269 }
270
271 int
272 md_post_extract(void)
273 {
274 return 0;
275 }
276
277 void
278 md_cleanup_install(void)
279 {
280 #ifndef DEBUG
281 enable_rc_conf();
282 #endif
283 msg_display(MSG_howtoboot);
284 process_menu(MENU_ok, NULL);
285 }
286
287 int
288 md_pre_update(void)
289 {
290 struct mbr_partition *part;
291 mbr_info_t *ext;
292 int i;
293
294 if (get_ramsize() <= 32)
295 set_swap(pm->diskdev, NULL);
296
297 read_mbr(pm->diskdev, &mbr);
298 /* do a sanity check of the partition table */
299 for (ext = &mbr; ext; ext = ext->extended) {
300 part = ext->mbr.mbr_parts;
301 for (i = 0; i < MBR_PART_COUNT; part++, i++) {
302 if (part->mbrp_type != MBR_PTYPE_FAT12)
303 continue;
304 if (part->mbrp_size < (MIN_FAT12_BOOT / 512)) {
305 msg_display(MSG_boottoosmall);
306 msg_display_add(MSG_nobootpart, 0);
307 process_menu(MENU_yesno, NULL);
308 if (!yesno)
309 return 0;
310 nobootfs = 1;
311 }
312 }
313 }
314 if (md_check_partitions() == 0)
315 nobootfs = 1;
316 return 1;
317 }
318
319 /* Upgrade support */
320 int
321 md_update(void)
322 {
323 md_post_newfs();
324 return 1;
325 }
326
327 int
328 md_check_mbr(mbr_info_t *mbri)
329 {
330 mbr_info_t *ext;
331 struct mbr_partition *part;
332 int i;
333
334 for (ext = mbri; ext; ext = ext->extended) {
335 part = ext->mbr.mbr_parts;
336 for (i = 0; i < MBR_PART_COUNT; part++, i++) {
337 if (part->mbrp_type == MBR_PTYPE_FAT12) {
338 pm->bootstart = part->mbrp_start;
339 pm->bootsize = part->mbrp_size;
340 break;
341 }
342 }
343 }
344 if (pm->bootsize < (MIN_FAT12_BOOT / 512)) {
345 msg_display(MSG_boottoosmall);
346 msg_display_add(MSG_reeditpart, 0);
347 process_menu(MENU_yesno, NULL);
348 if (!yesno)
349 return 0;
350 return 1;
351 }
352 if (pm->bootstart == 0 || pm->bootsize == 0) {
353 msg_display(MSG_nobootpart);
354 msg_display_add(MSG_reeditpart, 0);
355 process_menu(MENU_yesno, NULL);
356 if (!yesno)
357 return 0;
358 return 1;
359 }
360 return 2;
361 }
362
363 int
364 md_mbr_use_wholedisk(mbr_info_t *mbri)
365 {
366 struct mbr_sector *mbrs = &mbri->mbr;
367 mbr_info_t *ext;
368 struct mbr_partition *part;
369
370 part = &mbrs->mbr_parts[0];
371 /* Set the partition information for full disk usage. */
372 while ((ext = mbri->extended)) {
373 mbri->extended = ext->extended;
374 free(ext);
375 }
376 memset(part, 0, MBR_PART_COUNT * sizeof *part);
377 #ifdef BOOTSEL
378 memset(&mbri->mbrb, 0, sizeof mbri->mbrb);
379 #endif
380 part[0].mbrp_type = MBR_PTYPE_FAT12;
381 part[0].mbrp_size = FAT12_BOOT_SIZE / 512;
382 part[0].mbrp_start = bsec;
383 part[0].mbrp_flag = MBR_PFLAG_ACTIVE;
384
385 part[1].mbrp_type = MBR_PTYPE_NETBSD;
386 part[1].mbrp_size = pm->dlsize - (bsec + FAT12_BOOT_SIZE / 512);
387 part[1].mbrp_start = bsec + FAT12_BOOT_SIZE / 512;
388 part[1].mbrp_flag = 0;
389
390 pm->ptstart = part[1].mbrp_start;
391 pm->ptsize = part[1].mbrp_size;
392 pm->bootstart = part[0].mbrp_start;
393 pm->bootsize = part[0].mbrp_size;
394 return 1;
395 }
396
397 int
398 md_pre_mount()
399 {
400 return 0;
401 }
402