Fri Dec 2 04:05:20 2011 UTC ()
Add missing -F flag and -I flag in usage.  Sort the order to match
manpage.


(enami)
diff -r1.136 -r1.137 src/sbin/fdisk/fdisk.c

cvs diff -r1.136 -r1.137 src/sbin/fdisk/fdisk.c (switch to unified diff)

--- src/sbin/fdisk/fdisk.c 2011/12/02 03:04:11 1.136
+++ src/sbin/fdisk/fdisk.c 2011/12/02 04:05:20 1.137
@@ -1,1606 +1,1606 @@ @@ -1,1606 +1,1606 @@
1/* $NetBSD: fdisk.c,v 1.136 2011/12/02 03:04:11 christos Exp $ */ 1/* $NetBSD: fdisk.c,v 1.137 2011/12/02 04:05:20 enami Exp $ */
2 2
3/* 3/*
4 * Mach Operating System 4 * Mach Operating System
5 * Copyright (c) 1992 Carnegie Mellon University 5 * Copyright (c) 1992 Carnegie Mellon University
6 * All Rights Reserved. 6 * All Rights Reserved.
7 * 7 *
8 * Permission to use, copy, modify and distribute this software and its 8 * Permission to use, copy, modify and distribute this software and its
9 * documentation is hereby granted, provided that both the copyright 9 * documentation is hereby granted, provided that both the copyright
10 * notice and this permission notice appear in all copies of the 10 * notice and this permission notice appear in all copies of the
11 * software, derivative works or modified versions, and any portions 11 * software, derivative works or modified versions, and any portions
12 * thereof, and that both notices appear in supporting documentation. 12 * thereof, and that both notices appear in supporting documentation.
13 * 13 *
14 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 14 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
15 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 15 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
16 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 16 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
17 * 17 *
18 * Carnegie Mellon requests users of this software to return to 18 * Carnegie Mellon requests users of this software to return to
19 * 19 *
20 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 20 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
21 * School of Computer Science 21 * School of Computer Science
22 * Carnegie Mellon University 22 * Carnegie Mellon University
23 * Pittsburgh PA 15213-3890 23 * Pittsburgh PA 15213-3890
24 * 24 *
25 * any improvements or extensions that they make and grant Carnegie Mellon 25 * any improvements or extensions that they make and grant Carnegie Mellon
26 * the rights to redistribute these changes. 26 * the rights to redistribute these changes.
27 */ 27 */
28 28
29/* 29/*
30 * 14-Dec-89 Robert Baron (rvb) at Carnegie-Mellon University 30 * 14-Dec-89 Robert Baron (rvb) at Carnegie-Mellon University
31 * Copyright (c) 1989 Robert. V. Baron 31 * Copyright (c) 1989 Robert. V. Baron
32 * Created. 32 * Created.
33 */ 33 */
34 34
35#if HAVE_NBTOOL_CONFIG_H 35#if HAVE_NBTOOL_CONFIG_H
36#include "nbtool_config.h" 36#include "nbtool_config.h"
37#endif 37#endif
38 38
39#include <sys/cdefs.h> 39#include <sys/cdefs.h>
40 40
41#ifndef lint 41#ifndef lint
42__RCSID("$NetBSD: fdisk.c,v 1.136 2011/12/02 03:04:11 christos Exp $"); 42__RCSID("$NetBSD: fdisk.c,v 1.137 2011/12/02 04:05:20 enami Exp $");
43#endif /* not lint */ 43#endif /* not lint */
44 44
45#define MBRPTYPENAMES 45#define MBRPTYPENAMES
46#include <sys/types.h> 46#include <sys/types.h>
47#include <sys/param.h> 47#include <sys/param.h>
48#include <sys/stat.h> 48#include <sys/stat.h>
49#include <ctype.h> 49#include <ctype.h>
50#include <err.h> 50#include <err.h>
51#include <errno.h> 51#include <errno.h>
52#include <fcntl.h> 52#include <fcntl.h>
53#include <paths.h> 53#include <paths.h>
54#include <stdarg.h> 54#include <stdarg.h>
55#include <stddef.h> 55#include <stddef.h>
56#include <stdio.h> 56#include <stdio.h>
57#include <stdlib.h> 57#include <stdlib.h>
58#include <string.h> 58#include <string.h>
59#include <unistd.h> 59#include <unistd.h>
60#include <vis.h> 60#include <vis.h>
61 61
62#if !HAVE_NBTOOL_CONFIG_H 62#if !HAVE_NBTOOL_CONFIG_H
63#include <sys/disklabel.h> 63#include <sys/disklabel.h>
64#include <sys/disklabel_gpt.h> 64#include <sys/disklabel_gpt.h>
65#include <sys/bootblock.h> 65#include <sys/bootblock.h>
66#include <sys/ioctl.h> 66#include <sys/ioctl.h>
67#include <sys/sysctl.h> 67#include <sys/sysctl.h>
68#include <disktab.h> 68#include <disktab.h>
69#include <util.h> 69#include <util.h>
70#include <zlib.h> 70#include <zlib.h>
71#else 71#else
72#include <nbinclude/sys/disklabel.h> 72#include <nbinclude/sys/disklabel.h>
73#include <nbinclude/sys/disklabel_gpt.h> 73#include <nbinclude/sys/disklabel_gpt.h>
74#include <nbinclude/sys/bootblock.h> 74#include <nbinclude/sys/bootblock.h>
75#include "../../include/disktab.h" 75#include "../../include/disktab.h"
76/* We enforce -F, so none of these possibly undefined items can be needed */ 76/* We enforce -F, so none of these possibly undefined items can be needed */
77#define opendisk(path, fl, buf, buflen, cooked) (-1) 77#define opendisk(path, fl, buf, buflen, cooked) (-1)
78#ifndef DIOCGDEFLABEL 78#ifndef DIOCGDEFLABEL
79#define DIOCGDEFLABEL 0 79#define DIOCGDEFLABEL 0
80#endif 80#endif
81#ifndef DIOCGDINFO 81#ifndef DIOCGDINFO
82#define DIOCGDINFO 0 82#define DIOCGDINFO 0
83#endif 83#endif
84#ifndef DIOCWLABEL 84#ifndef DIOCWLABEL
85#define DIOCWLABEL 0 85#define DIOCWLABEL 0
86#endif 86#endif
87#endif /* HAVE_NBTOOL_CONFIG_H */ 87#endif /* HAVE_NBTOOL_CONFIG_H */
88 88
89#define DEFAULT_BOOTDIR "/usr/mdec" 89#define DEFAULT_BOOTDIR "/usr/mdec"
90 90
91#define LE_MBR_MAGIC htole16(MBR_MAGIC) 91#define LE_MBR_MAGIC htole16(MBR_MAGIC)
92#define LE_MBR_BS_MAGIC htole16(MBR_BS_MAGIC) 92#define LE_MBR_BS_MAGIC htole16(MBR_BS_MAGIC)
93 93
94#if defined(__i386__) || defined(__x86_64__) 94#if defined(__i386__) || defined(__x86_64__)
95#if !HAVE_NBTOOL_CONFIG_H 95#if !HAVE_NBTOOL_CONFIG_H
96#include <machine/cpu.h> 96#include <machine/cpu.h>
97#endif /* !HAVE_NBTOOL_CONFIG_H */ 97#endif /* !HAVE_NBTOOL_CONFIG_H */
98#define BOOTSEL 98#define BOOTSEL
99#endif 99#endif
100 100
101#ifdef BOOTSEL 101#ifdef BOOTSEL
102 102
103#define DEFAULT_BOOTCODE "mbr" 103#define DEFAULT_BOOTCODE "mbr"
104#define DEFAULT_BOOTSELCODE "mbr_bootsel" 104#define DEFAULT_BOOTSELCODE "mbr_bootsel"
105#define DEFAULT_BOOTEXTCODE "mbr_ext" 105#define DEFAULT_BOOTEXTCODE "mbr_ext"
106 106
107/* Scan values for the various keys we use, as returned by the BIOS */ 107/* Scan values for the various keys we use, as returned by the BIOS */
108#define SCAN_ENTER 0x1c 108#define SCAN_ENTER 0x1c
109#define SCAN_F1 0x3b 109#define SCAN_F1 0x3b
110#define SCAN_1 0x2 110#define SCAN_1 0x2
111 111
112 112
113#define MAX_BIOS_DISKS 16 /* Going beyond F12 is hard though! */ 113#define MAX_BIOS_DISKS 16 /* Going beyond F12 is hard though! */
114 114
115/* We same the dflt 'boot partition' as a disk block, with some magic values. */ 115/* We same the dflt 'boot partition' as a disk block, with some magic values. */
116#define DEFAULT_ACTIVE (~(daddr_t)0) 116#define DEFAULT_ACTIVE (~(daddr_t)0)
117#define DEFAULT_DISK(n) (DEFAULT_ACTIVE - MAX_BIOS_DISKS + (n)) 117#define DEFAULT_DISK(n) (DEFAULT_ACTIVE - MAX_BIOS_DISKS + (n))
118 118
119#endif 119#endif
120 120
121#define GPT_TYPE(offs) ((offs) == GPT_HDR_BLKNO ? "primary" : "secondary") 121#define GPT_TYPE(offs) ((offs) == GPT_HDR_BLKNO ? "primary" : "secondary")
122 122
123#ifndef PRIdaddr 123#ifndef PRIdaddr
124#define PRIdaddr PRId64 124#define PRIdaddr PRId64
125#endif 125#endif
126 126
127#ifndef _PATH_DEFDISK 127#ifndef _PATH_DEFDISK
128#define _PATH_DEFDISK "/dev/rwd0d" 128#define _PATH_DEFDISK "/dev/rwd0d"
129#endif 129#endif
130 130
131struct { 131struct {
132 struct mbr_sector *ptn; /* array of pbrs */ 132 struct mbr_sector *ptn; /* array of pbrs */
133 daddr_t base; /* first sector of ext. ptn */ 133 daddr_t base; /* first sector of ext. ptn */
134 daddr_t limit; /* last sector of ext. ptn */ 134 daddr_t limit; /* last sector of ext. ptn */
135 int num_ptn; /* number of contained partitions */ 135 int num_ptn; /* number of contained partitions */
136 int ptn_id; /* entry in mbr */ 136 int ptn_id; /* entry in mbr */
137 int is_corrupt; /* 1 if extended chain illegal */ 137 int is_corrupt; /* 1 if extended chain illegal */
138} ext; 138} ext;
139 139
140#define LBUF 100 140#define LBUF 100
141static char lbuf[LBUF]; 141static char lbuf[LBUF];
142 142
143static const char *disk = _PATH_DEFDISK; 143static const char *disk = _PATH_DEFDISK;
144 144
145static struct disklabel disklabel; /* disk parameters */ 145static struct disklabel disklabel; /* disk parameters */
146 146
147static struct mbr_sector mboot; 147static struct mbr_sector mboot;
148 148
149static const char *boot_dir = DEFAULT_BOOTDIR; 149static const char *boot_dir = DEFAULT_BOOTDIR;
150static char *boot_path = NULL; /* name of file we actually opened */ 150static char *boot_path = NULL; /* name of file we actually opened */
151 151
152#ifdef BOOTSEL 152#ifdef BOOTSEL
153#define BOOTSEL_OPTIONS "B" 153#define BOOTSEL_OPTIONS "B"
154#else 154#else
155#define BOOTSEL_OPTIONS  155#define BOOTSEL_OPTIONS
156#define change_part(e, p, id, st, sz, bm) change__part(e, p, id, st, sz) 156#define change_part(e, p, id, st, sz, bm) change__part(e, p, id, st, sz)
157#endif 157#endif
158#define OPTIONS BOOTSEL_OPTIONS "0123FSafiluvA:b:c:E:r:s:w:" 158#define OPTIONS BOOTSEL_OPTIONS "0123FSafiluvA:b:c:E:r:s:w:"
159 159
160/* 160/*
161 * Disk geometry and partition alignment. 161 * Disk geometry and partition alignment.
162 * 162 *
163 * Modern disks do not have a fixed geomery and will always give a 'faked' 163 * Modern disks do not have a fixed geomery and will always give a 'faked'
164 * geometry that matches the ATA standard - max 16 heads and 256 sec/track. 164 * geometry that matches the ATA standard - max 16 heads and 256 sec/track.
165 * The ATA geometry allows access to 2^28 sectors (as does LBA mode). 165 * The ATA geometry allows access to 2^28 sectors (as does LBA mode).
166 * 166 *
167 * The BIOS calls originally used an 8bit register for cylinder, head and 167 * The BIOS calls originally used an 8bit register for cylinder, head and
168 * sector. Later 2 bits were stolen from the sector number and added to 168 * sector. Later 2 bits were stolen from the sector number and added to
169 * cylinder number. The BIOS will translate this faked geometry either to 169 * cylinder number. The BIOS will translate this faked geometry either to
170 * the geometry reported by the disk, or do LBA reads (possibly LBA48). 170 * the geometry reported by the disk, or do LBA reads (possibly LBA48).
171 * BIOS CHS reads have all sorts of limits, but 2^24 is absolute. 171 * BIOS CHS reads have all sorts of limits, but 2^24 is absolute.
172 * For historic reasons the BIOS geometry is the called the dos geometry! 172 * For historic reasons the BIOS geometry is the called the dos geometry!
173 * 173 *
174 * If you know the disks real geometry it is usually worth aligning 174 * If you know the disks real geometry it is usually worth aligning
175 * disk partitions to cylinder boundaries (certainly traditional!). 175 * disk partitions to cylinder boundaries (certainly traditional!).
176 * For 'mbr' disks this has always been done with the BIOS geometry. 176 * For 'mbr' disks this has always been done with the BIOS geometry.
177 * The first track (typically 63 sectors) is reserved because the first 177 * The first track (typically 63 sectors) is reserved because the first
178 * sector is used for boot code. Similarly the data partition in an 178 * sector is used for boot code. Similarly the data partition in an
179 * extended partition will start one track in. If an extended partition 179 * extended partition will start one track in. If an extended partition
180 * starts at the beginning of the disk you lose 2 tracks. 180 * starts at the beginning of the disk you lose 2 tracks.
181 * 181 *
182 * However non-magnetic media in particular has physical sectors that are 182 * However non-magnetic media in particular has physical sectors that are
183 * not the same size as those reported, so has to do read modify write 183 * not the same size as those reported, so has to do read modify write
184 * sequences for misaligned transfers. The alignment of partitions to 184 * sequences for misaligned transfers. The alignment of partitions to
185 * cylinder boundaries makes this happen all the time. 185 * cylinder boundaries makes this happen all the time.
186 * 186 *
187 * It is thus sensible to align partitions on a sensible sector boundary. 187 * It is thus sensible to align partitions on a sensible sector boundary.
188 * For instance 1MB (2048 sectors). 188 * For instance 1MB (2048 sectors).
189 * Common code can do this by using a geometry with 1 head and 2048 189 * Common code can do this by using a geometry with 1 head and 2048
190 * sectors per track. 190 * sectors per track.
191 */ 191 */
192 192
193/* Disks reported geometry and overall size from device driver */ 193/* Disks reported geometry and overall size from device driver */
194static unsigned int cylinders, sectors, heads; 194static unsigned int cylinders, sectors, heads;
195static daddr_t disksectors; 195static daddr_t disksectors;
196#define cylindersectors (heads * sectors) 196#define cylindersectors (heads * sectors)
197 197
198/* Geometry from the BIOS */ 198/* Geometry from the BIOS */
199static unsigned int dos_cylinders; 199static unsigned int dos_cylinders;
200static unsigned int dos_heads; 200static unsigned int dos_heads;
201static unsigned int dos_sectors; 201static unsigned int dos_sectors;
202static daddr_t dos_disksectors; 202static daddr_t dos_disksectors;
203#define dos_cylindersectors (dos_heads * dos_sectors) 203#define dos_cylindersectors (dos_heads * dos_sectors)
204#define dos_totalsectors (dos_heads * dos_sectors * dos_cylinders) 204#define dos_totalsectors (dos_heads * dos_sectors * dos_cylinders)
205 205
206#define DOSSECT(s,c) (((s) & 0x3f) | (((c) >> 2) & 0xc0)) 206#define DOSSECT(s,c) (((s) & 0x3f) | (((c) >> 2) & 0xc0))
207#define DOSCYL(c) ((c) & 0xff) 207#define DOSCYL(c) ((c) & 0xff)
208#define SEC_IN_1M (1024 * 1024 / 512) 208#define SEC_IN_1M (1024 * 1024 / 512)
209#define SEC_TO_MB(sec) ((unsigned int)(((sec) + SEC_IN_1M / 2) / SEC_IN_1M)) 209#define SEC_TO_MB(sec) ((unsigned int)(((sec) + SEC_IN_1M / 2) / SEC_IN_1M))
210#define SEC_TO_CYL(sec) (((sec) + dos_cylindersectors/2) / dos_cylindersectors) 210#define SEC_TO_CYL(sec) (((sec) + dos_cylindersectors/2) / dos_cylindersectors)
211 211
212#define MAXCYL 1024 /* Usual limit is 1023 */ 212#define MAXCYL 1024 /* Usual limit is 1023 */
213#define MAXHEAD 256 /* Usual limit is 255 */ 213#define MAXHEAD 256 /* Usual limit is 255 */
214#define MAXSECTOR 63 214#define MAXSECTOR 63
215static int partition = -1; 215static int partition = -1;
216 216
217/* Alignment of partition, and offset if first sector unusable */ 217/* Alignment of partition, and offset if first sector unusable */
218static unsigned int ptn_alignment; /* default dos_cylindersectors */ 218static unsigned int ptn_alignment; /* default dos_cylindersectors */
219static unsigned int ptn_0_offset; /* default dos_sectors */ 219static unsigned int ptn_0_offset; /* default dos_sectors */
220 220
221static int fd = -1, wfd = -1, *rfd = &fd; 221static int fd = -1, wfd = -1, *rfd = &fd;
222static char *disk_file = NULL; 222static char *disk_file = NULL;
223static char *disk_type = NULL; 223static char *disk_type = NULL;
224 224
225static int a_flag; /* set active partition */ 225static int a_flag; /* set active partition */
226static int i_flag; /* init bootcode */ 226static int i_flag; /* init bootcode */
227static int I_flag; /* ignore errors */ 227static int I_flag; /* ignore errors */
228static int u_flag; /* update partition data */ 228static int u_flag; /* update partition data */
229static int v_flag; /* more verbose */ 229static int v_flag; /* more verbose */
230static int sh_flag; /* Output data as shell defines */ 230static int sh_flag; /* Output data as shell defines */
231static int f_flag; /* force --not interactive */ 231static int f_flag; /* force --not interactive */
232static int s_flag; /* set id,offset,size */ 232static int s_flag; /* set id,offset,size */
233static int b_flag; /* Set cyl, heads, secs (as c/h/s) */ 233static int b_flag; /* Set cyl, heads, secs (as c/h/s) */
234static int B_flag; /* Edit/install bootselect code */ 234static int B_flag; /* Edit/install bootselect code */
235static int E_flag; /* extended partition number */ 235static int E_flag; /* extended partition number */
236static int b_cyl, b_head, b_sec; /* b_flag values. */ 236static int b_cyl, b_head, b_sec; /* b_flag values. */
237 237
238#if !HAVE_NBTOOL_CONFIG_H 238#if !HAVE_NBTOOL_CONFIG_H
239static int F_flag = 0; 239static int F_flag = 0;
240#else 240#else
241/* Tool - force 'file' mode to avoid unsupported functions and ioctls */ 241/* Tool - force 'file' mode to avoid unsupported functions and ioctls */
242static int F_flag = 1; 242static int F_flag = 1;
243#endif 243#endif
244 244
245static struct gpt_hdr gpt1, gpt2; /* GUID partition tables */ 245static struct gpt_hdr gpt1, gpt2; /* GUID partition tables */
246 246
247static struct mbr_sector bootcode[8192 / sizeof (struct mbr_sector)]; 247static struct mbr_sector bootcode[8192 / sizeof (struct mbr_sector)];
248static int bootsize; /* actual size of bootcode */ 248static int bootsize; /* actual size of bootcode */
249static int boot_installed; /* 1 if we've copied code into the mbr */ 249static int boot_installed; /* 1 if we've copied code into the mbr */
250 250
251#if (defined(__i386__) || defined(__x86_64__)) && !HAVE_NBTOOL_CONFIG_H 251#if (defined(__i386__) || defined(__x86_64__)) && !HAVE_NBTOOL_CONFIG_H
252#define USE_DISKLIST 252#define USE_DISKLIST
253static struct disklist *dl; 253static struct disklist *dl;
254#endif 254#endif
255 255
256 256
257#define KNOWN_SYSIDS (sizeof(mbr_ptypes)/sizeof(mbr_ptypes[0])) 257#define KNOWN_SYSIDS (sizeof(mbr_ptypes)/sizeof(mbr_ptypes[0]))
258 258
259__dead static void usage(void); 259__dead static void usage(void);
260static void print_s0(int); 260static void print_s0(int);
261static void print_part(struct mbr_sector *, int, daddr_t); 261static void print_part(struct mbr_sector *, int, daddr_t);
262static void print_mbr_partition(struct mbr_sector *, int, daddr_t, daddr_t, int); 262static void print_mbr_partition(struct mbr_sector *, int, daddr_t, daddr_t, int);
263static void print_pbr(daddr_t, int, uint8_t); 263static void print_pbr(daddr_t, int, uint8_t);
264static int is_all_zero(const unsigned char *, size_t); 264static int is_all_zero(const unsigned char *, size_t);
265static void printvis(int, const char *, const char *, size_t); 265static void printvis(int, const char *, const char *, size_t);
266static int read_boot(const char *, void *, size_t, int); 266static int read_boot(const char *, void *, size_t, int);
267static void init_sector0(int); 267static void init_sector0(int);
268static void intuit_translated_geometry(void); 268static void intuit_translated_geometry(void);
269static void get_bios_geometry(void); 269static void get_bios_geometry(void);
270static void get_extended_ptn(void); 270static void get_extended_ptn(void);
271static void get_ptn_alignmemt(void); 271static void get_ptn_alignmemt(void);
272#if defined(USE_DISKLIST) 272#if defined(USE_DISKLIST)
273static void get_diskname(const char *, char *, size_t); 273static void get_diskname(const char *, char *, size_t);
274#endif 274#endif
275static int change_part(int, int, int, daddr_t, daddr_t, char *); 275static int change_part(int, int, int, daddr_t, daddr_t, char *);
276static void print_geometry(void); 276static void print_geometry(void);
277static int first_active(void); 277static int first_active(void);
278static void change_active(int); 278static void change_active(int);
279static void change_bios_geometry(void); 279static void change_bios_geometry(void);
280static void dos(int, unsigned char *, unsigned char *, unsigned char *); 280static void dos(int, unsigned char *, unsigned char *, unsigned char *);
281static int open_disk(int); 281static int open_disk(int);
282static int read_disk(daddr_t, void *); 282static int read_disk(daddr_t, void *);
283static int write_disk(daddr_t, void *); 283static int write_disk(daddr_t, void *);
284static int get_params(void); 284static int get_params(void);
285static int read_s0(daddr_t, struct mbr_sector *); 285static int read_s0(daddr_t, struct mbr_sector *);
286static int write_mbr(void); 286static int write_mbr(void);
287static int read_gpt(daddr_t, struct gpt_hdr *); 287static int read_gpt(daddr_t, struct gpt_hdr *);
288static int delete_gpt(struct gpt_hdr *); 288static int delete_gpt(struct gpt_hdr *);
289static int yesno(const char *, ...); 289static int yesno(const char *, ...);
290static int64_t decimal(const char *, int64_t, int, int64_t, int64_t); 290static int64_t decimal(const char *, int64_t, int, int64_t, int64_t);
291#define DEC_SEC 1 /* asking for a sector number */ 291#define DEC_SEC 1 /* asking for a sector number */
292#define DEC_RND 2 /* round to end of first track */ 292#define DEC_RND 2 /* round to end of first track */
293#define DEC_RND_0 4 /* convert 0 to size of a track */ 293#define DEC_RND_0 4 /* convert 0 to size of a track */
294#define DEC_RND_DOWN 8 /* subtract 1 track */ 294#define DEC_RND_DOWN 8 /* subtract 1 track */
295#define DEC_RND_DOWN_2 16 /* subtract 2 tracks */ 295#define DEC_RND_DOWN_2 16 /* subtract 2 tracks */
296static int ptn_id(const char *, int *); 296static int ptn_id(const char *, int *);
297static int type_match(const void *, const void *); 297static int type_match(const void *, const void *);
298static const char *get_type(int); 298static const char *get_type(int);
299static int get_mapping(int, unsigned int *, unsigned int *, unsigned int *, unsigned long *); 299static int get_mapping(int, unsigned int *, unsigned int *, unsigned int *, unsigned long *);
300#ifdef BOOTSEL 300#ifdef BOOTSEL
301static daddr_t configure_bootsel(daddr_t); 301static daddr_t configure_bootsel(daddr_t);
302static void install_bootsel(int); 302static void install_bootsel(int);
303static daddr_t get_default_boot(void); 303static daddr_t get_default_boot(void);
304static void set_default_boot(daddr_t); 304static void set_default_boot(daddr_t);
305static void string(const char *, int, char *); 305static void string(const char *, int, char *);
306#endif 306#endif
307 307
308static void 308static void
309initvar_disk(const char **diskp) 309initvar_disk(const char **diskp)
310{ 310{
311#if !HAVE_NBTOOL_CONFIG_H 311#if !HAVE_NBTOOL_CONFIG_H
312 int mib[2]; 312 int mib[2];
313 size_t len; 313 size_t len;
314 char *root_device; 314 char *root_device;
315 315
316 mib[0] = CTL_KERN; 316 mib[0] = CTL_KERN;
317 mib[1] = KERN_ROOT_DEVICE; 317 mib[1] = KERN_ROOT_DEVICE;
318 if (sysctl(mib, 2, NULL, &len, NULL, 0) == -1 || 318 if (sysctl(mib, 2, NULL, &len, NULL, 0) == -1 ||
319 (root_device = malloc(len)) == NULL || 319 (root_device = malloc(len)) == NULL ||
320 sysctl(mib, 2, root_device, &len, NULL, 0) == -1) 320 sysctl(mib, 2, root_device, &len, NULL, 0) == -1)
321 return; 321 return;
322 322
323 *diskp = root_device; 323 *diskp = root_device;
324#endif /* HAVE_NBTOOL_CONFIG_H */ 324#endif /* HAVE_NBTOOL_CONFIG_H */
325} 325}
326 326
327int 327int
328main(int argc, char *argv[]) 328main(int argc, char *argv[])
329{ 329{
330 struct stat sb; 330 struct stat sb;
331 int ch; 331 int ch;
332 size_t len; 332 size_t len;
333 char *cp; 333 char *cp;
334 int n; 334 int n;
335#ifdef BOOTSEL 335#ifdef BOOTSEL
336 daddr_t default_ptn; /* start sector of default ptn */ 336 daddr_t default_ptn; /* start sector of default ptn */
337 char *cbootmenu = 0; 337 char *cbootmenu = 0;
338#endif 338#endif
339 339
340 int csysid; /* For the s_flag. */ 340 int csysid; /* For the s_flag. */
341 unsigned int cstart, csize; 341 unsigned int cstart, csize;
342 a_flag = u_flag = sh_flag = f_flag = s_flag = b_flag = 0; 342 a_flag = u_flag = sh_flag = f_flag = s_flag = b_flag = 0;
343 i_flag = B_flag = 0; 343 i_flag = B_flag = 0;
344 v_flag = 0; 344 v_flag = 0;
345 E_flag = 0; 345 E_flag = 0;
346 csysid = cstart = csize = 0; 346 csysid = cstart = csize = 0;
347 while ((ch = getopt(argc, argv, OPTIONS)) != -1) { 347 while ((ch = getopt(argc, argv, OPTIONS)) != -1) {
348 switch (ch) { 348 switch (ch) {
349 case '0': 349 case '0':
350 partition = 0; 350 partition = 0;
351 break; 351 break;
352 case '1': 352 case '1':
353 partition = 1; 353 partition = 1;
354 break; 354 break;
355 case '2': 355 case '2':
356 partition = 2; 356 partition = 2;
357 break; 357 break;
358 case '3': 358 case '3':
359 partition = 3; 359 partition = 3;
360 break; 360 break;
361 case 'E': /* Extended partition number */ 361 case 'E': /* Extended partition number */
362 E_flag = 1; 362 E_flag = 1;
363 partition = strtoul(optarg, &cp, 0); 363 partition = strtoul(optarg, &cp, 0);
364 if (*cp || partition < 0) 364 if (*cp || partition < 0)
365 errx(1, "Bad partition number -E %s.", optarg); 365 errx(1, "Bad partition number -E %s.", optarg);
366 break; 366 break;
367#ifdef BOOTSEL 367#ifdef BOOTSEL
368 case 'B': /* Bootselect parameters */ 368 case 'B': /* Bootselect parameters */
369 B_flag = 1; 369 B_flag = 1;
370 break; 370 break;
371#endif 371#endif
372 case 'F': /* device argument is really a file */ 372 case 'F': /* device argument is really a file */
373 F_flag = 1; 373 F_flag = 1;
374 break; 374 break;
375 case 'S': /* Output as shell variables */ 375 case 'S': /* Output as shell variables */
376 sh_flag = 1; 376 sh_flag = 1;
377 break; 377 break;
378 case 'a': /* Set active partition */ 378 case 'a': /* Set active partition */
379 a_flag = 1; 379 a_flag = 1;
380 break; 380 break;
381 case 'f': /* Non interactive */ 381 case 'f': /* Non interactive */
382 f_flag = 1; 382 f_flag = 1;
383 break; 383 break;
384 case 'i': /* Always update bootcode */ 384 case 'i': /* Always update bootcode */
385 i_flag = 1; 385 i_flag = 1;
386 break; 386 break;
387 case 'I': /* Ignore errors */ 387 case 'I': /* Ignore errors */
388 I_flag = 1; 388 I_flag = 1;
389 break; 389 break;
390 case 'l': /* List known partition types */ 390 case 'l': /* List known partition types */
391 for (len = 0; len < KNOWN_SYSIDS; len++) 391 for (len = 0; len < KNOWN_SYSIDS; len++)
392 printf("%03d %s\n", mbr_ptypes[len].id, 392 printf("%03d %s\n", mbr_ptypes[len].id,
393 mbr_ptypes[len].name); 393 mbr_ptypes[len].name);
394 return 0; 394 return 0;
395 case 'u': /* Update partition details */ 395 case 'u': /* Update partition details */
396 u_flag = 1; 396 u_flag = 1;
397 break; 397 break;
398 case 'v': /* Be verbose */ 398 case 'v': /* Be verbose */
399 v_flag++; 399 v_flag++;
400 break; 400 break;
401 case 's': /* Partition details */ 401 case 's': /* Partition details */
402 s_flag = 1; 402 s_flag = 1;
403 if (sscanf(optarg, "%d/%u/%u%n", &csysid, &cstart, 403 if (sscanf(optarg, "%d/%u/%u%n", &csysid, &cstart,
404 &csize, &n) == 3) { 404 &csize, &n) == 3) {
405 if (optarg[n] == 0) 405 if (optarg[n] == 0)
406 break; 406 break;
407#ifdef BOOTSEL 407#ifdef BOOTSEL
408 if (optarg[n] == '/') { 408 if (optarg[n] == '/') {
409 cbootmenu = optarg + n + 1; 409 cbootmenu = optarg + n + 1;
410 break; 410 break;
411 } 411 }
412#endif 412#endif
413 } 413 }
414 errx(1, "Bad argument to the -s flag."); 414 errx(1, "Bad argument to the -s flag.");
415 break; 415 break;
416 case 'b': /* BIOS geometry */ 416 case 'b': /* BIOS geometry */
417 b_flag = 1; 417 b_flag = 1;
418 if (sscanf(optarg, "%d/%d/%d%n", &b_cyl, &b_head, 418 if (sscanf(optarg, "%d/%d/%d%n", &b_cyl, &b_head,
419 &b_sec, &n) != 3 || optarg[n] != 0) 419 &b_sec, &n) != 3 || optarg[n] != 0)
420 errx(1, "Bad argument to the -b flag."); 420 errx(1, "Bad argument to the -b flag.");
421 if (b_cyl > MAXCYL) 421 if (b_cyl > MAXCYL)
422 b_cyl = MAXCYL; 422 b_cyl = MAXCYL;
423 break; 423 break;
424 case 'A': /* Partition alignment[/offset] */ 424 case 'A': /* Partition alignment[/offset] */
425 if (sscanf(optarg, "%u%n/%u%n", &ptn_alignment, 425 if (sscanf(optarg, "%u%n/%u%n", &ptn_alignment,
426 &n, &ptn_0_offset, &n) < 1 426 &n, &ptn_0_offset, &n) < 1
427 || optarg[n] != 0 427 || optarg[n] != 0
428 || ptn_0_offset > ptn_alignment) 428 || ptn_0_offset > ptn_alignment)
429 errx(1, "Bad argument to the -A flag."); 429 errx(1, "Bad argument to the -A flag.");
430 if (ptn_0_offset == 0) 430 if (ptn_0_offset == 0)
431 ptn_0_offset = ptn_alignment; 431 ptn_0_offset = ptn_alignment;
432 break; 432 break;
433 case 'c': /* file/directory containing boot code */ 433 case 'c': /* file/directory containing boot code */
434 if (strchr(optarg, '/') != NULL && 434 if (strchr(optarg, '/') != NULL &&
435 stat(optarg, &sb) == 0 && 435 stat(optarg, &sb) == 0 &&
436 (sb.st_mode & S_IFMT) == S_IFDIR) { 436 (sb.st_mode & S_IFMT) == S_IFDIR) {
437 boot_dir = optarg; 437 boot_dir = optarg;
438 break; 438 break;
439 } 439 }
440 bootsize = read_boot(optarg, bootcode, 440 bootsize = read_boot(optarg, bootcode,
441 sizeof bootcode, 1); 441 sizeof bootcode, 1);
442 i_flag = 1; 442 i_flag = 1;
443 break; 443 break;
444 case 'r': /* read data from disk_file (not raw disk) */ 444 case 'r': /* read data from disk_file (not raw disk) */
445 rfd = &wfd; 445 rfd = &wfd;
446 /* FALLTHROUGH */ 446 /* FALLTHROUGH */
447 case 'w': /* write data to disk_file */ 447 case 'w': /* write data to disk_file */
448 disk_file = optarg; 448 disk_file = optarg;
449 break; 449 break;
450 case 't': 450 case 't':
451 if (setdisktab(optarg) == -1) 451 if (setdisktab(optarg) == -1)
452 errx(EXIT_FAILURE, "bad disktab"); 452 errx(EXIT_FAILURE, "bad disktab");
453 break; 453 break;
454 case 'T': 454 case 'T':
455 disk_type = optarg; 455 disk_type = optarg;
456 break; 456 break;
457 default: 457 default:
458 usage(); 458 usage();
459 } 459 }
460 } 460 }
461 argc -= optind; 461 argc -= optind;
462 argv += optind; 462 argv += optind;
463 463
464 if (disk_type != NULL && getdiskbyname(disk_type) == NULL) 464 if (disk_type != NULL && getdiskbyname(disk_type) == NULL)
465 errx(EXIT_FAILURE, "bad disktype"); 465 errx(EXIT_FAILURE, "bad disktype");
466 466
467 if (sh_flag && (a_flag || i_flag || u_flag || f_flag || s_flag)) 467 if (sh_flag && (a_flag || i_flag || u_flag || f_flag || s_flag))
468 usage(); 468 usage();
469 469
470 if (B_flag && f_flag) { 470 if (B_flag && f_flag) {
471 warnx("Bootselector may only be configured interactively"); 471 warnx("Bootselector may only be configured interactively");
472 usage(); 472 usage();
473 } 473 }
474 474
475 if (f_flag && u_flag && !s_flag) { 475 if (f_flag && u_flag && !s_flag) {
476 warnx("Partition data not specified"); 476 warnx("Partition data not specified");
477 usage(); 477 usage();
478 } 478 }
479 479
480 if (s_flag && partition == -1) { 480 if (s_flag && partition == -1) {
481 warnx("-s flag requires a partition selected."); 481 warnx("-s flag requires a partition selected.");
482 usage(); 482 usage();
483 } 483 }
484 484
485 if (argc > 1) 485 if (argc > 1)
486 usage(); 486 usage();
487 487
488 if (argc > 0) 488 if (argc > 0)
489 disk = argv[0]; 489 disk = argv[0];
490 else if (!F_flag) { 490 else if (!F_flag) {
491 /* Default to boot device */ 491 /* Default to boot device */
492 initvar_disk(&disk); 492 initvar_disk(&disk);
493 } 493 }
494 494
495 if (!F_flag && stat(disk, &sb) == 0 && S_ISREG(sb.st_mode)) 495 if (!F_flag && stat(disk, &sb) == 0 && S_ISREG(sb.st_mode))
496 F_flag = 1; 496 F_flag = 1;
497 497
498 if (open_disk(B_flag || a_flag || i_flag || u_flag) < 0) 498 if (open_disk(B_flag || a_flag || i_flag || u_flag) < 0)
499 exit(1); 499 exit(1);
500 500
501 if (read_s0(0, &mboot)) 501 if (read_s0(0, &mboot))
502 /* must have been a blank disk */ 502 /* must have been a blank disk */
503 init_sector0(1); 503 init_sector0(1);
504 504
505 read_gpt(GPT_HDR_BLKNO, &gpt1); 505 read_gpt(GPT_HDR_BLKNO, &gpt1);
506 read_gpt(disksectors - 1, &gpt2); 506 read_gpt(disksectors - 1, &gpt2);
507 507
508 if (b_flag) { 508 if (b_flag) {
509 dos_cylinders = b_cyl; 509 dos_cylinders = b_cyl;
510 dos_heads = b_head; 510 dos_heads = b_head;
511 dos_sectors = b_sec; 511 dos_sectors = b_sec;
512 } else { 512 } else {
513 get_bios_geometry(); 513 get_bios_geometry();
514 } 514 }
515 515
516 if (ptn_alignment == 0) 516 if (ptn_alignment == 0)
517 get_ptn_alignmemt(); 517 get_ptn_alignmemt();
518 518
519 get_extended_ptn(); 519 get_extended_ptn();
520 520
521#ifdef BOOTSEL 521#ifdef BOOTSEL
522 default_ptn = get_default_boot(); 522 default_ptn = get_default_boot();
523#endif 523#endif
524 524
525 if (E_flag && !u_flag && partition >= ext.num_ptn) 525 if (E_flag && !u_flag && partition >= ext.num_ptn)
526 errx(1, "Extended partition %d is not defined.", partition); 526 errx(1, "Extended partition %d is not defined.", partition);
527 527
528 /* Do the update stuff! */ 528 /* Do the update stuff! */
529 if (u_flag) { 529 if (u_flag) {
530 if (!f_flag && !b_flag) 530 if (!f_flag && !b_flag)
531 change_bios_geometry(); 531 change_bios_geometry();
532 532
533 if (s_flag) 533 if (s_flag)
534 change_part(E_flag, partition, csysid, cstart, csize, 534 change_part(E_flag, partition, csysid, cstart, csize,
535 cbootmenu); 535 cbootmenu);
536 else { 536 else {
537 int part = partition, chg_ext = E_flag, prompt = 1; 537 int part = partition, chg_ext = E_flag, prompt = 1;
538 do { 538 do {
539 if (prompt) { 539 if (prompt) {
540 printf("\n"); 540 printf("\n");
541 print_s0(partition); 541 print_s0(partition);
542 } 542 }
543 if (partition == -1) 543 if (partition == -1)
544 part = ptn_id( 544 part = ptn_id(
545 "Which partition do you want to change?", 545 "Which partition do you want to change?",
546 &chg_ext); 546 &chg_ext);
547 if (part < 0) 547 if (part < 0)
548 break; 548 break;
549 prompt = change_part(chg_ext, part, 0, 0, 0, 0); 549 prompt = change_part(chg_ext, part, 0, 0, 0, 0);
550 } while (partition == -1); 550 } while (partition == -1);
551 } 551 }
552 } else { 552 } else {
553 if (!i_flag && !B_flag) { 553 if (!i_flag && !B_flag) {
554 print_geometry(); 554 print_geometry();
555 print_s0(partition); 555 print_s0(partition);
556 } 556 }
557 } 557 }
558 558
559 if (a_flag && !E_flag) 559 if (a_flag && !E_flag)
560 change_active(partition); 560 change_active(partition);
561 561
562#ifdef BOOTSEL 562#ifdef BOOTSEL
563 if (B_flag || u_flag || i_flag) 563 if (B_flag || u_flag || i_flag)
564 /* Ensure the mbr code supports this configuration */ 564 /* Ensure the mbr code supports this configuration */
565 install_bootsel(0); 565 install_bootsel(0);
566 if (B_flag) 566 if (B_flag)
567 default_ptn = configure_bootsel(default_ptn); 567 default_ptn = configure_bootsel(default_ptn);
568 set_default_boot(default_ptn); 568 set_default_boot(default_ptn);
569#else 569#else
570 if (i_flag) 570 if (i_flag)
571 init_sector0(0); 571 init_sector0(0);
572#endif 572#endif
573 573
574 if (u_flag || a_flag || i_flag || B_flag) { 574 if (u_flag || a_flag || i_flag || B_flag) {
575 if (!f_flag) { 575 if (!f_flag) {
576 printf("\nWe haven't written the MBR back to disk " 576 printf("\nWe haven't written the MBR back to disk "
577 "yet. This is your last chance.\n"); 577 "yet. This is your last chance.\n");
578 if (u_flag) 578 if (u_flag)
579 print_s0(-1); 579 print_s0(-1);
580 if (gpt1.hdr_size != 0 || gpt2.hdr_size != 0) 580 if (gpt1.hdr_size != 0 || gpt2.hdr_size != 0)
581 printf("\nWARNING: The disk is carrying " 581 printf("\nWARNING: The disk is carrying "
582 "GUID Partition Tables.\n" 582 "GUID Partition Tables.\n"
583 " If you continue, " 583 " If you continue, "
584 "GPT headers will be deleted.\n\n"); 584 "GPT headers will be deleted.\n\n");
585 if (yesno("Should we write new partition table?")) { 585 if (yesno("Should we write new partition table?")) {
586 delete_gpt(&gpt1); 586 delete_gpt(&gpt1);
587 delete_gpt(&gpt2); 587 delete_gpt(&gpt2);
588 write_mbr(); 588 write_mbr();
589 } 589 }
590 } else { 590 } else {
591 if (delete_gpt(&gpt1) > 0) 591 if (delete_gpt(&gpt1) > 0)
592 warnx("Primary GPT header was deleted"); 592 warnx("Primary GPT header was deleted");
593 if (delete_gpt(&gpt2) > 0) 593 if (delete_gpt(&gpt2) > 0)
594 warnx("Secondary GPT header was deleted"); 594 warnx("Secondary GPT header was deleted");
595 write_mbr(); 595 write_mbr();
596 } 596 }
597 } 597 }
598 598
599 exit(0); 599 exit(0);
600} 600}
601 601
602static void 602static void
603usage(void) 603usage(void)
604{ 604{
605 int indent = 7 + (int)strlen(getprogname()) + 1; 605 int indent = 7 + (int)strlen(getprogname()) + 1;
606 606
607 (void)fprintf(stderr, "usage: %s [-afiluvBS] " 607 (void)fprintf(stderr, "usage: %s [-aBFfIilSuv] "
608 "[-A ptn_alignment[/ptn_0_offset]] \\\n" 608 "[-A ptn_alignment[/ptn_0_offset]] \\\n"
609 "%*s[-b cylinders/heads/sectors] \\\n" 609 "%*s[-b cylinders/heads/sectors] \\\n"
610 "%*s[-0123 | -E num " 610 "%*s[-0123 | -E num "
611 "[-s id/start/size[/bootmenu]]] \\\n" 611 "[-s id/start/size[/bootmenu]]] \\\n"
612 "%*s[-t disktab] [-T disktype] \\\n" 612 "%*s[-t disktab] [-T disktype] \\\n"
613 "%*s[-c bootcode] " 613 "%*s[-c bootcode] "
614 "[-r|-w file] [device]\n" 614 "[-r|-w file] [device]\n"
615 "\t-a change active partition\n" 615 "\t-a change active partition\n"
616 "\t-f force - not interactive\n" 616 "\t-f force - not interactive\n"
617 "\t-i initialise MBR code\n" 617 "\t-i initialise MBR code\n"
618 "\t-l list partition types\n" 618 "\t-l list partition types\n"
619 "\t-u update partition data\n" 619 "\t-u update partition data\n"
620 "\t-v verbose output, -v -v more verbose still\n" 620 "\t-v verbose output, -v -v more verbose still\n"
621 "\t-B update bootselect options\n" 621 "\t-B update bootselect options\n"
622 "\t-F treat device as a regular file\n" 622 "\t-F treat device as a regular file\n"
623 "\t-S output as shell defines\n" 623 "\t-S output as shell defines\n"
624 "\t-r and -w access 'file' for non-destructive testing\n", 624 "\t-r and -w access 'file' for non-destructive testing\n",
625 getprogname(), indent, "", indent, "", indent, "", indent, ""); 625 getprogname(), indent, "", indent, "", indent, "", indent, "");
626 exit(1); 626 exit(1);
627} 627}
628 628
629static daddr_t 629static daddr_t
630ext_offset(int part) 630ext_offset(int part)
631{ 631{
632 daddr_t offset = ext.base; 632 daddr_t offset = ext.base;
633 633
634 if (part != 0) 634 if (part != 0)
635 offset += le32toh(ext.ptn[part - 1].mbr_parts[1].mbrp_start); 635 offset += le32toh(ext.ptn[part - 1].mbr_parts[1].mbrp_start);
636 return offset; 636 return offset;
637} 637}
638 638
639static void 639static void
640print_s0(int which) 640print_s0(int which)
641{ 641{
642 int part; 642 int part;
643 643
644 if (which == -1) { 644 if (which == -1) {
645 if (!sh_flag) 645 if (!sh_flag)
646 printf("Partition table:\n"); 646 printf("Partition table:\n");
647 for (part = 0; part < MBR_PART_COUNT; part++) { 647 for (part = 0; part < MBR_PART_COUNT; part++) {
648 if (!sh_flag) 648 if (!sh_flag)
649 printf("%d: ", part); 649 printf("%d: ", part);
650 print_part(&mboot, part, 0); 650 print_part(&mboot, part, 0);
651 } 651 }
652 if (!sh_flag) { 652 if (!sh_flag) {
653 if (ext.is_corrupt) 653 if (ext.is_corrupt)
654 printf("Extended partition table is corrupt\n"); 654 printf("Extended partition table is corrupt\n");
655 else 655 else
656 if (ext.num_ptn != 0) 656 if (ext.num_ptn != 0)
657 printf("Extended partition table:\n"); 657 printf("Extended partition table:\n");
658 } 658 }
659 for (part = 0; part < ext.num_ptn; part++) { 659 for (part = 0; part < ext.num_ptn; part++) {
660 if (!sh_flag) 660 if (!sh_flag)
661 printf("E%d: ", part); 661 printf("E%d: ", part);
662 print_part(&ext.ptn[part], 0, ext_offset(part)); 662 print_part(&ext.ptn[part], 0, ext_offset(part));
663 if (!sh_flag && v_flag >= 2) { 663 if (!sh_flag && v_flag >= 2) {
664 printf("link: "); 664 printf("link: ");
665 print_mbr_partition(&ext.ptn[part], 1, 665 print_mbr_partition(&ext.ptn[part], 1,
666 ext_offset(part), ext.base, 0); 666 ext_offset(part), ext.base, 0);
667 } 667 }
668 } 668 }
669#ifdef BOOTSEL 669#ifdef BOOTSEL
670 if (!sh_flag && mboot.mbr_bootsel_magic == LE_MBR_BS_MAGIC) { 670 if (!sh_flag && mboot.mbr_bootsel_magic == LE_MBR_BS_MAGIC) {
671 int tmo; 671 int tmo;
672 672
673 printf("Bootselector "); 673 printf("Bootselector ");
674 if (mboot.mbr_bootsel.mbrbs_flags & MBR_BS_ACTIVE) { 674 if (mboot.mbr_bootsel.mbrbs_flags & MBR_BS_ACTIVE) {
675 printf("enabled"); 675 printf("enabled");
676 tmo = le16toh(mboot.mbr_bootsel.mbrbs_timeo); 676 tmo = le16toh(mboot.mbr_bootsel.mbrbs_timeo);
677 if (tmo == 0xffff) 677 if (tmo == 0xffff)
678 printf(", infinite timeout"); 678 printf(", infinite timeout");
679 else 679 else
680 printf(", timeout %d seconds", 680 printf(", timeout %d seconds",
681 (10 * tmo + 9) / 182); 681 (10 * tmo + 9) / 182);
682 } else 682 } else
683 printf("disabled"); 683 printf("disabled");
684 printf(".\n"); 684 printf(".\n");
685 } 685 }
686#endif 686#endif
687 if (!sh_flag) { 687 if (!sh_flag) {
688 int active = first_active(); 688 int active = first_active();
689 if (active == MBR_PART_COUNT) 689 if (active == MBR_PART_COUNT)
690 printf("No active partition.\n"); 690 printf("No active partition.\n");
691 else 691 else
692 printf("First active partition: %d\n", active); 692 printf("First active partition: %d\n", active);
693 } 693 }
694 if (!sh_flag && mboot.mbr_dsn != 0) 694 if (!sh_flag && mboot.mbr_dsn != 0)
695 printf("Drive serial number: %"PRIu32" (0x%08x)\n", 695 printf("Drive serial number: %"PRIu32" (0x%08x)\n",
696 le32toh(mboot.mbr_dsn), 696 le32toh(mboot.mbr_dsn),
697 le32toh(mboot.mbr_dsn)); 697 le32toh(mboot.mbr_dsn));
698 return; 698 return;
699 } 699 }
700 700
701 if (E_flag) { 701 if (E_flag) {
702 if (!sh_flag) 702 if (!sh_flag)
703 printf("Extended partition E%d:\n", which); 703 printf("Extended partition E%d:\n", which);
704 if (which > ext.num_ptn) 704 if (which > ext.num_ptn)
705 printf("Undefined\n"); 705 printf("Undefined\n");
706 else 706 else
707 print_part(&ext.ptn[which], 0, ext_offset(which)); 707 print_part(&ext.ptn[which], 0, ext_offset(which));
708 } else { 708 } else {
709 if (!sh_flag) 709 if (!sh_flag)
710 printf("Partition %d:\n", which); 710 printf("Partition %d:\n", which);
711 print_part(&mboot, which, 0); 711 print_part(&mboot, which, 0);
712 } 712 }
713} 713}
714 714
715static void 715static void
716print_part(struct mbr_sector *boot, int part, daddr_t offset) 716print_part(struct mbr_sector *boot, int part, daddr_t offset)
717{ 717{
718 struct mbr_partition *partp; 718 struct mbr_partition *partp;
719 const char *e; 719 const char *e;
720 720
721 if (!sh_flag) { 721 if (!sh_flag) {
722 print_mbr_partition(boot, part, offset, 0, 0); 722 print_mbr_partition(boot, part, offset, 0, 0);
723 return; 723 return;
724 } 724 }
725 725
726 partp = &boot->mbr_parts[part]; 726 partp = &boot->mbr_parts[part];
727 if (boot != &mboot) { 727 if (boot != &mboot) {
728 part = boot - ext.ptn; 728 part = boot - ext.ptn;
729 e = "E"; 729 e = "E";
730 } else 730 } else
731 e = ""; 731 e = "";
732 732
733 if (partp->mbrp_type == 0) { 733 if (partp->mbrp_type == 0) {
734 printf("PART%s%dSIZE=0\n", e, part); 734 printf("PART%s%dSIZE=0\n", e, part);
735 return; 735 return;
736 } 736 }
737 737
738 printf("PART%s%dID=%d\n", e, part, partp->mbrp_type); 738 printf("PART%s%dID=%d\n", e, part, partp->mbrp_type);
739 printf("PART%s%dSIZE=%u\n", e, part, le32toh(partp->mbrp_size)); 739 printf("PART%s%dSIZE=%u\n", e, part, le32toh(partp->mbrp_size));
740 printf("PART%s%dSTART=%"PRIdaddr"\n", e, part, 740 printf("PART%s%dSTART=%"PRIdaddr"\n", e, part,
741 offset + le32toh(partp->mbrp_start)); 741 offset + le32toh(partp->mbrp_start));
742 printf("PART%s%dFLAG=0x%x\n", e, part, partp->mbrp_flag); 742 printf("PART%s%dFLAG=0x%x\n", e, part, partp->mbrp_flag);
743 printf("PART%s%dBCYL=%d\n", e, part, 743 printf("PART%s%dBCYL=%d\n", e, part,
744 MBR_PCYL(partp->mbrp_scyl, partp->mbrp_ssect)); 744 MBR_PCYL(partp->mbrp_scyl, partp->mbrp_ssect));
745 printf("PART%s%dBHEAD=%d\n", e, part, partp->mbrp_shd); 745 printf("PART%s%dBHEAD=%d\n", e, part, partp->mbrp_shd);
746 printf("PART%s%dBSEC=%d\n", e, part, MBR_PSECT(partp->mbrp_ssect)); 746 printf("PART%s%dBSEC=%d\n", e, part, MBR_PSECT(partp->mbrp_ssect));
747 printf("PART%s%dECYL=%d\n", e, part, 747 printf("PART%s%dECYL=%d\n", e, part,
748 MBR_PCYL(partp->mbrp_ecyl, partp->mbrp_esect)); 748 MBR_PCYL(partp->mbrp_ecyl, partp->mbrp_esect));
749 printf("PART%s%dEHEAD=%d\n", e, part, partp->mbrp_ehd); 749 printf("PART%s%dEHEAD=%d\n", e, part, partp->mbrp_ehd);
750 printf("PART%s%dESEC=%d\n", e, part, MBR_PSECT(partp->mbrp_esect)); 750 printf("PART%s%dESEC=%d\n", e, part, MBR_PSECT(partp->mbrp_esect));
751} 751}
752 752
753static void 753static void
754pr_cyls(daddr_t sector, int is_end) 754pr_cyls(daddr_t sector, int is_end)
755{ 755{
756 unsigned long cyl, head, sect; 756 unsigned long cyl, head, sect;
757 cyl = sector / dos_cylindersectors; 757 cyl = sector / dos_cylindersectors;
758 sect = sector - cyl * dos_cylindersectors; 758 sect = sector - cyl * dos_cylindersectors;
759 head = sect / dos_sectors; 759 head = sect / dos_sectors;
760 sect -= head * dos_sectors; 760 sect -= head * dos_sectors;
761 761
762 printf("%lu", cyl); 762 printf("%lu", cyl);
763 763
764 if (is_end) { 764 if (is_end) {
765 if (head == dos_heads - 1 && sect == dos_sectors - 1) 765 if (head == dos_heads - 1 && sect == dos_sectors - 1)
766 return; 766 return;
767 } else { 767 } else {
768 if (head == 0 && sect == 0) 768 if (head == 0 && sect == 0)
769 return; 769 return;
770 } 770 }
771 771
772 printf("/%lu/%lu", head, sect + 1); 772 printf("/%lu/%lu", head, sect + 1);
773} 773}
774 774
775static void 775static void
776print_mbr_partition(struct mbr_sector *boot, int part, 776print_mbr_partition(struct mbr_sector *boot, int part,
777 daddr_t offset, daddr_t exoffset, int indent) 777 daddr_t offset, daddr_t exoffset, int indent)
778{ 778{
779 daddr_t start; 779 daddr_t start;
780 daddr_t size; 780 daddr_t size;
781 struct mbr_partition *partp = &boot->mbr_parts[part]; 781 struct mbr_partition *partp = &boot->mbr_parts[part];
782 struct mbr_sector eboot; 782 struct mbr_sector eboot;
783 int p; 783 int p;
784 static int dumped = 0; 784 static int dumped = 0;
785 785
786 if (partp->mbrp_type == 0 && v_flag < 2) { 786 if (partp->mbrp_type == 0 && v_flag < 2) {
787 printf("<UNUSED>\n"); 787 printf("<UNUSED>\n");
788 return; 788 return;
789 } 789 }
790 790
791 start = le32toh(partp->mbrp_start); 791 start = le32toh(partp->mbrp_start);
792 size = le32toh(partp->mbrp_size); 792 size = le32toh(partp->mbrp_size);
793 if (MBR_IS_EXTENDED(partp->mbrp_type)) 793 if (MBR_IS_EXTENDED(partp->mbrp_type))
794 start += exoffset; 794 start += exoffset;
795 else 795 else
796 start += offset; 796 start += offset;
797 797
798 printf("%s (sysid %d)\n", get_type(partp->mbrp_type), partp->mbrp_type); 798 printf("%s (sysid %d)\n", get_type(partp->mbrp_type), partp->mbrp_type);
799#ifdef BOOTSEL 799#ifdef BOOTSEL
800 if (boot->mbr_bootsel_magic == LE_MBR_BS_MAGIC && 800 if (boot->mbr_bootsel_magic == LE_MBR_BS_MAGIC &&
801 boot->mbr_bootsel.mbrbs_nametab[part][0]) 801 boot->mbr_bootsel.mbrbs_nametab[part][0])
802 printf("%*s bootmenu: %s\n", indent, "", 802 printf("%*s bootmenu: %s\n", indent, "",
803 boot->mbr_bootsel.mbrbs_nametab[part]); 803 boot->mbr_bootsel.mbrbs_nametab[part]);
804#endif 804#endif
805 805
806 printf("%*s start %"PRIdaddr", size %"PRIdaddr, 806 printf("%*s start %"PRIdaddr", size %"PRIdaddr,
807 indent, "", start, size); 807 indent, "", start, size);
808 if (size != 0) { 808 if (size != 0) {
809 printf(" (%u MB, Cyls ", SEC_TO_MB(size)); 809 printf(" (%u MB, Cyls ", SEC_TO_MB(size));
810 if (v_flag == 0 && le32toh(partp->mbrp_start) == ptn_0_offset) 810 if (v_flag == 0 && le32toh(partp->mbrp_start) == ptn_0_offset)
811 pr_cyls(start - ptn_0_offset, 0); 811 pr_cyls(start - ptn_0_offset, 0);
812 else 812 else
813 pr_cyls(start, 0); 813 pr_cyls(start, 0);
814 printf("-"); 814 printf("-");
815 pr_cyls(start + size - 1, 1); 815 pr_cyls(start + size - 1, 1);
816 printf(")"); 816 printf(")");
817 } 817 }
818 818
819 switch (partp->mbrp_flag) { 819 switch (partp->mbrp_flag) {
820 case 0: 820 case 0:
821 break; 821 break;
822 case MBR_PFLAG_ACTIVE: 822 case MBR_PFLAG_ACTIVE:
823 printf(", Active"); 823 printf(", Active");
824 break; 824 break;
825 default: 825 default:
826 printf(", flag 0x%x", partp->mbrp_flag); 826 printf(", flag 0x%x", partp->mbrp_flag);
827 break; 827 break;
828 } 828 }
829 printf("\n"); 829 printf("\n");
830 830
831 if (v_flag) { 831 if (v_flag) {
832 printf("%*s beg: cylinder %4d, head %3d, sector %2d\n", 832 printf("%*s beg: cylinder %4d, head %3d, sector %2d\n",
833 indent, "", 833 indent, "",
834 MBR_PCYL(partp->mbrp_scyl, partp->mbrp_ssect), 834 MBR_PCYL(partp->mbrp_scyl, partp->mbrp_ssect),
835 partp->mbrp_shd, MBR_PSECT(partp->mbrp_ssect)); 835 partp->mbrp_shd, MBR_PSECT(partp->mbrp_ssect));
836 printf("%*s end: cylinder %4d, head %3d, sector %2d\n", 836 printf("%*s end: cylinder %4d, head %3d, sector %2d\n",
837 indent, "", 837 indent, "",
838 MBR_PCYL(partp->mbrp_ecyl, partp->mbrp_esect), 838 MBR_PCYL(partp->mbrp_ecyl, partp->mbrp_esect),
839 partp->mbrp_ehd, MBR_PSECT(partp->mbrp_esect)); 839 partp->mbrp_ehd, MBR_PSECT(partp->mbrp_esect));
840 } 840 }
841 841
842 if (partp->mbrp_type == 0 && start == 0 && v_flag < 3) 842 if (partp->mbrp_type == 0 && start == 0 && v_flag < 3)
843 return; 843 return;
844 844
845 if (! MBR_IS_EXTENDED(partp->mbrp_type)) 845 if (! MBR_IS_EXTENDED(partp->mbrp_type))
846 print_pbr(start, indent + 8, partp->mbrp_type); 846 print_pbr(start, indent + 8, partp->mbrp_type);
847 847
848 if (!MBR_IS_EXTENDED(partp->mbrp_type) || 848 if (!MBR_IS_EXTENDED(partp->mbrp_type) ||
849 (v_flag <= 2 && !ext.is_corrupt)) 849 (v_flag <= 2 && !ext.is_corrupt))
850 return; 850 return;
851 851
852 /* 852 /*
853 * Recursive dump extended table, 853 * Recursive dump extended table,
854 * This is read from the disk - so is wrong during editing. 854 * This is read from the disk - so is wrong during editing.
855 * Just ensure we only show it once. 855 * Just ensure we only show it once.
856 */ 856 */
857 if (dumped) 857 if (dumped)
858 return; 858 return;
859 859
860 printf("%*s Extended partition table:\n", indent, ""); 860 printf("%*s Extended partition table:\n", indent, "");
861 indent += 4; 861 indent += 4;
862 if (read_s0(start, &eboot) == -1) 862 if (read_s0(start, &eboot) == -1)
863 return; 863 return;
864 for (p = 0; p < MBR_PART_COUNT; p++) { 864 for (p = 0; p < MBR_PART_COUNT; p++) {
865 printf("%*s%d: ", indent, "", p); 865 printf("%*s%d: ", indent, "", p);
866 print_mbr_partition(&eboot, p, start, 866 print_mbr_partition(&eboot, p, start,
867 exoffset ? exoffset : start, indent); 867 exoffset ? exoffset : start, indent);
868 } 868 }
869 869
870 if (exoffset == 0) 870 if (exoffset == 0)
871 dumped = 1; 871 dumped = 1;
872} 872}
873 873
874/* Print a line with a label and a vis-encoded string */ 874/* Print a line with a label and a vis-encoded string */
875static void 875static void
876printvis(int indent, const char *label, const char *buf, size_t size) 876printvis(int indent, const char *label, const char *buf, size_t size)
877{ 877{
878 char *visbuf; 878 char *visbuf;
879 879
880 if ((visbuf = malloc(size * 4 + 1)) == NULL) 880 if ((visbuf = malloc(size * 4 + 1)) == NULL)
881 err(1, "Malloc failed"); 881 err(1, "Malloc failed");
882 strsvisx(visbuf, buf, size, VIS_TAB|VIS_NL|VIS_OCTAL, "\""); 882 strsvisx(visbuf, buf, size, VIS_TAB|VIS_NL|VIS_OCTAL, "\"");
883 printf("%*s%s: \"%s\"\n", 883 printf("%*s%s: \"%s\"\n",
884 indent, "", 884 indent, "",
885 label, visbuf); 885 label, visbuf);
886 free(visbuf); 886 free(visbuf);
887} 887}
888 888
889/* Check whether a buffer contains all bytes zero */ 889/* Check whether a buffer contains all bytes zero */
890static int 890static int
891is_all_zero(const unsigned char *p, size_t size) 891is_all_zero(const unsigned char *p, size_t size)
892{ 892{
893 893
894 while (size-- > 0) { 894 while (size-- > 0) {
895 if (*p++ != 0) 895 if (*p++ != 0)
896 return 0; 896 return 0;
897 } 897 }
898 return 1; 898 return 1;
899} 899}
900 900
901/* 901/*
902 * Report on the contents of a PBR sector. 902 * Report on the contents of a PBR sector.
903 * 903 *
904 * We first perform several sanity checks. If vflag >= 2, we report all 904 * We first perform several sanity checks. If vflag >= 2, we report all
905 * failing tests, but for smaller values of v_flag we stop after the 905 * failing tests, but for smaller values of v_flag we stop after the
906 * first failing test. Tests are ordered in an attempt to get the most 906 * first failing test. Tests are ordered in an attempt to get the most
907 * useful error message from the first failing test. 907 * useful error message from the first failing test.
908 * 908 *
909 * If v_flag >= 2, we also report some decoded values from the PBR. 909 * If v_flag >= 2, we also report some decoded values from the PBR.
910 * These results may be meaningless, if the PBR doesn't follow common 910 * These results may be meaningless, if the PBR doesn't follow common
911 * conventions. 911 * conventions.
912 * 912 *
913 * Trying to decode anything more than the magic number in the last 913 * Trying to decode anything more than the magic number in the last
914 * two bytes is a layering violation, but it can be very useful in 914 * two bytes is a layering violation, but it can be very useful in
915 * diagnosing boot failures. 915 * diagnosing boot failures.
916 */ 916 */
917static void 917static void
918print_pbr(daddr_t sector, int indent, uint8_t part_type) 918print_pbr(daddr_t sector, int indent, uint8_t part_type)
919{ 919{
920 struct mbr_sector pboot; 920 struct mbr_sector pboot;
921 unsigned char *p, *endp; 921 unsigned char *p, *endp;
922 unsigned char val; 922 unsigned char val;
923 int ok; 923 int ok;
924 int errcount = 0; 924 int errcount = 0;
925 925
926#define PBR_ERROR(...) \ 926#define PBR_ERROR(...) \
927 do { \ 927 do { \
928 ++errcount; \ 928 ++errcount; \
929 printf("%*s%s: ", indent, "", \ 929 printf("%*s%s: ", indent, "", \
930 (v_flag < 2 ? "PBR is not bootable" : "Not bootable")); \ 930 (v_flag < 2 ? "PBR is not bootable" : "Not bootable")); \
931 printf(__VA_ARGS__); \ 931 printf(__VA_ARGS__); \
932 if (v_flag < 2) \ 932 if (v_flag < 2) \
933 return; \ 933 return; \
934 } while (/*CONSTCOND*/ 0) 934 } while (/*CONSTCOND*/ 0)
935 935
936 if (v_flag >= 2) { 936 if (v_flag >= 2) {
937 printf("%*sInformation from PBR:\n", 937 printf("%*sInformation from PBR:\n",
938 indent, ""); 938 indent, "");
939 indent += 4; 939 indent += 4;
940 } 940 }
941 941
942 if (read_disk(sector, &pboot) == -1) { 942 if (read_disk(sector, &pboot) == -1) {
943 PBR_ERROR("Sector %"PRIdaddr" is unreadable (%s)\n", 943 PBR_ERROR("Sector %"PRIdaddr" is unreadable (%s)\n",
944 sector, strerror(errno)); 944 sector, strerror(errno));
945 return; 945 return;
946 } 946 }
947 947
948 /* all bytes identical? */ 948 /* all bytes identical? */
949 p = (unsigned char *)&pboot; 949 p = (unsigned char *)&pboot;
950 endp = p + sizeof(pboot); 950 endp = p + sizeof(pboot);
951 val = *p; 951 val = *p;
952 ok = 0; 952 ok = 0;
953 for (; p < endp; p++) { 953 for (; p < endp; p++) {
954 if (*p != val) { 954 if (*p != val) {
955 ok = 1; 955 ok = 1;
956 break; 956 break;
957 } 957 }
958 } 958 }
959 if (! ok) 959 if (! ok)
960 PBR_ERROR("All bytes are identical (0x%02x)\n", val); 960 PBR_ERROR("All bytes are identical (0x%02x)\n", val);
961 961
962 if (pboot.mbr_magic != LE_MBR_MAGIC) 962 if (pboot.mbr_magic != LE_MBR_MAGIC)
963 PBR_ERROR("Bad magic number (0x%04x)\n", 963 PBR_ERROR("Bad magic number (0x%04x)\n",
964 le16toh(pboot.mbr_magic)); 964 le16toh(pboot.mbr_magic));
965 965
966#if 0 966#if 0
967 /* Some i386 OS might fail this test. All non-i386 will fail. */ 967 /* Some i386 OS might fail this test. All non-i386 will fail. */
968 if (pboot.mbr_jmpboot[0] != 0xE9 968 if (pboot.mbr_jmpboot[0] != 0xE9
969 && pboot.mbr_jmpboot[0] != 0xEB) { 969 && pboot.mbr_jmpboot[0] != 0xEB) {
970 PBR_ERROR("Does not begin with i386 JMP instruction" 970 PBR_ERROR("Does not begin with i386 JMP instruction"
971 " (0x%02x 0x%02x0 0x%02x)\n", 971 " (0x%02x 0x%02x0 0x%02x)\n",
972 pboot.mbr_jmpboot[0], pboot.mbr_jmpboot[1], 972 pboot.mbr_jmpboot[0], pboot.mbr_jmpboot[1],
973 pboot.mbr_jmpboot[2]); 973 pboot.mbr_jmpboot[2]);
974 } 974 }
975#endif 975#endif
976 976
977 if (v_flag > 0 && errcount == 0) 977 if (v_flag > 0 && errcount == 0)
978 printf("%*sPBR appears to be bootable\n", 978 printf("%*sPBR appears to be bootable\n",
979 indent, ""); 979 indent, "");
980 if (v_flag < 2) 980 if (v_flag < 2)
981 return; 981 return;
982 982
983 if (! is_all_zero(pboot.mbr_oemname, sizeof(pboot.mbr_oemname))) { 983 if (! is_all_zero(pboot.mbr_oemname, sizeof(pboot.mbr_oemname))) {
984 printvis(indent, "OEM name", (char *)pboot.mbr_oemname, 984 printvis(indent, "OEM name", (char *)pboot.mbr_oemname,
985 sizeof(pboot.mbr_oemname)); 985 sizeof(pboot.mbr_oemname));
986 } 986 }
987 987
988 if (pboot.mbr_bpb.bpb16.bsBootSig == 0x29) 988 if (pboot.mbr_bpb.bpb16.bsBootSig == 0x29)
989 printf("%*sBPB FAT16 boot signature found\n", 989 printf("%*sBPB FAT16 boot signature found\n",
990 indent, ""); 990 indent, "");
991 if (pboot.mbr_bpb.bpb32.bsBootSig == 0x29) 991 if (pboot.mbr_bpb.bpb32.bsBootSig == 0x29)
992 printf("%*sBPB FAT32 boot signature found\n", 992 printf("%*sBPB FAT32 boot signature found\n",
993 indent, ""); 993 indent, "");
994 994
995#undef PBR_ERROR 995#undef PBR_ERROR
996} 996}
997 997
998static int 998static int
999read_boot(const char *name, void *buf, size_t len, int err_exit) 999read_boot(const char *name, void *buf, size_t len, int err_exit)
1000{ 1000{
1001 int bfd, ret; 1001 int bfd, ret;
1002 struct stat st; 1002 struct stat st;
1003 1003
1004 if (boot_path != NULL) 1004 if (boot_path != NULL)
1005 free(boot_path); 1005 free(boot_path);
1006 if (strchr(name, '/') == 0) 1006 if (strchr(name, '/') == 0)
1007 asprintf(&boot_path, "%s/%s", boot_dir, name); 1007 asprintf(&boot_path, "%s/%s", boot_dir, name);
1008 else 1008 else
1009 boot_path = strdup(name); 1009 boot_path = strdup(name);
1010 if (boot_path == NULL) 1010 if (boot_path == NULL)
1011 err(1, "Malloc failed"); 1011 err(1, "Malloc failed");
1012 1012
1013 if ((bfd = open(boot_path, O_RDONLY)) < 0 || fstat(bfd, &st) == -1) { 1013 if ((bfd = open(boot_path, O_RDONLY)) < 0 || fstat(bfd, &st) == -1) {
1014 warn("%s", boot_path); 1014 warn("%s", boot_path);
1015 goto fail; 1015 goto fail;
1016 } 1016 }
1017 1017
1018 if (st.st_size > (off_t)len) { 1018 if (st.st_size > (off_t)len) {
1019 warnx("%s: bootcode too large", boot_path); 1019 warnx("%s: bootcode too large", boot_path);
1020 goto fail; 1020 goto fail;
1021 } 1021 }
1022 ret = st.st_size; 1022 ret = st.st_size;
1023 if (ret < 0x200) { 1023 if (ret < 0x200) {
1024 warnx("%s: bootcode too small", boot_path); 1024 warnx("%s: bootcode too small", boot_path);
1025 goto fail; 1025 goto fail;
1026 } 1026 }
1027 if (read(bfd, buf, len) != ret) { 1027 if (read(bfd, buf, len) != ret) {
1028 warn("%s", boot_path); 1028 warn("%s", boot_path);
1029 goto fail; 1029 goto fail;
1030 } 1030 }
1031 1031
1032 /* 1032 /*
1033 * Do some sanity checking here 1033 * Do some sanity checking here
1034 */ 1034 */
1035 if (((struct mbr_sector *)buf)->mbr_magic != LE_MBR_MAGIC) { 1035 if (((struct mbr_sector *)buf)->mbr_magic != LE_MBR_MAGIC) {
1036 warnx("%s: invalid magic", boot_path); 1036 warnx("%s: invalid magic", boot_path);
1037 goto fail; 1037 goto fail;
1038 } 1038 }
1039 1039
1040 close(bfd); 1040 close(bfd);
1041 ret = (ret + 0x1ff) & ~0x1ff; 1041 ret = (ret + 0x1ff) & ~0x1ff;
1042 return ret; 1042 return ret;
1043 1043
1044 fail: 1044 fail:
1045 if (bfd >= 0) 1045 if (bfd >= 0)
1046 close(bfd); 1046 close(bfd);
1047 if (err_exit) 1047 if (err_exit)
1048 exit(1); 1048 exit(1);
1049 return 0; 1049 return 0;
1050} 1050}
1051 1051
1052static void 1052static void
1053init_sector0(int zappart) 1053init_sector0(int zappart)
1054{ 1054{
1055 int i; 1055 int i;
1056 int copy_size = offsetof(struct mbr_sector, mbr_dsn); 1056 int copy_size = offsetof(struct mbr_sector, mbr_dsn);
1057 1057
1058#ifdef DEFAULT_BOOTCODE 1058#ifdef DEFAULT_BOOTCODE
1059 if (bootsize == 0) 1059 if (bootsize == 0)
1060 bootsize = read_boot(DEFAULT_BOOTCODE, bootcode, 1060 bootsize = read_boot(DEFAULT_BOOTCODE, bootcode,
1061 sizeof bootcode, 0); 1061 sizeof bootcode, 0);
1062#endif 1062#endif
1063#ifdef BOOTSEL 1063#ifdef BOOTSEL
1064 if (mboot.mbr_bootsel_magic == LE_MBR_BS_MAGIC 1064 if (mboot.mbr_bootsel_magic == LE_MBR_BS_MAGIC
1065 && bootcode[0].mbr_bootsel_magic == LE_MBR_BS_MAGIC) 1065 && bootcode[0].mbr_bootsel_magic == LE_MBR_BS_MAGIC)
1066 copy_size = MBR_BS_OFFSET; 1066 copy_size = MBR_BS_OFFSET;
1067#endif 1067#endif
1068 1068
1069 if (bootsize != 0) { 1069 if (bootsize != 0) {
1070 boot_installed = 1; 1070 boot_installed = 1;
1071 memcpy(&mboot, bootcode, copy_size); 1071 memcpy(&mboot, bootcode, copy_size);
1072 mboot.mbr_bootsel_magic = bootcode[0].mbr_bootsel_magic; 1072 mboot.mbr_bootsel_magic = bootcode[0].mbr_bootsel_magic;
1073 } 1073 }
1074 mboot.mbr_magic = LE_MBR_MAGIC; 1074 mboot.mbr_magic = LE_MBR_MAGIC;
1075  1075
1076 if (!zappart) 1076 if (!zappart)
1077 return; 1077 return;
1078 for (i = 0; i < MBR_PART_COUNT; i++) 1078 for (i = 0; i < MBR_PART_COUNT; i++)
1079 memset(&mboot.mbr_parts[i], 0, sizeof(mboot.mbr_parts[i])); 1079 memset(&mboot.mbr_parts[i], 0, sizeof(mboot.mbr_parts[i]));
1080} 1080}
1081 1081
1082static void 1082static void
1083get_extended_ptn(void) 1083get_extended_ptn(void)
1084{ 1084{
1085 struct mbr_partition *mp; 1085 struct mbr_partition *mp;
1086 struct mbr_sector *boot; 1086 struct mbr_sector *boot;
1087 daddr_t offset; 1087 daddr_t offset;
1088 struct mbr_sector *nptn; 1088 struct mbr_sector *nptn;
1089 1089
1090 /* find first (there should only be one) extended partition */ 1090 /* find first (there should only be one) extended partition */
1091 for (mp = mboot.mbr_parts; !MBR_IS_EXTENDED(mp->mbrp_type); mp++) 1091 for (mp = mboot.mbr_parts; !MBR_IS_EXTENDED(mp->mbrp_type); mp++)
1092 if (mp >= &mboot.mbr_parts[MBR_PART_COUNT]) 1092 if (mp >= &mboot.mbr_parts[MBR_PART_COUNT])
1093 return; 1093 return;
1094 1094
1095 /* 1095 /*
1096 * The extended partition should be structured as a linked list 1096 * The extended partition should be structured as a linked list
1097 * (even though it appears, at first glance, to be a tree). 1097 * (even though it appears, at first glance, to be a tree).
1098 */ 1098 */
1099 ext.base = le32toh(mp->mbrp_start); 1099 ext.base = le32toh(mp->mbrp_start);
1100 ext.limit = ext.base + le32toh(mp->mbrp_size); 1100 ext.limit = ext.base + le32toh(mp->mbrp_size);
1101 ext.ptn_id = mp - mboot.mbr_parts; 1101 ext.ptn_id = mp - mboot.mbr_parts;
1102 for (offset = 0;; offset = le32toh(boot->mbr_parts[1].mbrp_start)) { 1102 for (offset = 0;; offset = le32toh(boot->mbr_parts[1].mbrp_start)) {
1103 nptn = realloc(ext.ptn, (ext.num_ptn + 1) * sizeof *ext.ptn); 1103 nptn = realloc(ext.ptn, (ext.num_ptn + 1) * sizeof *ext.ptn);
1104 if (nptn == NULL) 1104 if (nptn == NULL)
1105 err(1, "Malloc failed"); 1105 err(1, "Malloc failed");
1106 ext.ptn = nptn; 1106 ext.ptn = nptn;
1107 boot = ext.ptn + ext.num_ptn; 1107 boot = ext.ptn + ext.num_ptn;
1108 if (read_s0(offset + ext.base, boot) == -1) 1108 if (read_s0(offset + ext.base, boot) == -1)
1109 break; 1109 break;
1110 /* expect p0 to be valid and p1 to be another extended ptn */ 1110 /* expect p0 to be valid and p1 to be another extended ptn */
1111 if (MBR_IS_EXTENDED(boot->mbr_parts[0].mbrp_type)) 1111 if (MBR_IS_EXTENDED(boot->mbr_parts[0].mbrp_type))
1112 break; 1112 break;
1113 if (boot->mbr_parts[1].mbrp_type != 0 && 1113 if (boot->mbr_parts[1].mbrp_type != 0 &&
1114 !MBR_IS_EXTENDED(boot->mbr_parts[1].mbrp_type)) 1114 !MBR_IS_EXTENDED(boot->mbr_parts[1].mbrp_type))
1115 break; 1115 break;
1116 /* p2 and p3 should be unallocated */ 1116 /* p2 and p3 should be unallocated */
1117 if (boot->mbr_parts[2].mbrp_type != 0 || 1117 if (boot->mbr_parts[2].mbrp_type != 0 ||
1118 boot->mbr_parts[3].mbrp_type != 0) 1118 boot->mbr_parts[3].mbrp_type != 0)
1119 break; 1119 break;
1120 /* data ptn inside extended one */ 1120 /* data ptn inside extended one */
1121 if (boot->mbr_parts[0].mbrp_type != 0 && 1121 if (boot->mbr_parts[0].mbrp_type != 0 &&
1122 offset + le32toh(boot->mbr_parts[0].mbrp_start) 1122 offset + le32toh(boot->mbr_parts[0].mbrp_start)
1123 + le32toh(boot->mbr_parts[0].mbrp_size) > ext.limit) 1123 + le32toh(boot->mbr_parts[0].mbrp_size) > ext.limit)
1124 break; 1124 break;
1125 1125
1126 ext.num_ptn++; 1126 ext.num_ptn++;
1127 1127
1128 if (boot->mbr_parts[1].mbrp_type == 0) 1128 if (boot->mbr_parts[1].mbrp_type == 0)
1129 /* end of extended partition chain */ 1129 /* end of extended partition chain */
1130 return; 1130 return;
1131 /* must be in sector order */ 1131 /* must be in sector order */
1132 if (offset >= le32toh(boot->mbr_parts[1].mbrp_start)) 1132 if (offset >= le32toh(boot->mbr_parts[1].mbrp_start))
1133 break; 1133 break;
1134 } 1134 }
1135 1135
1136 warnx("Extended partition table is corrupt\n"); 1136 warnx("Extended partition table is corrupt\n");
1137 ext.is_corrupt = 1; 1137 ext.is_corrupt = 1;
1138 ext.num_ptn = 0; 1138 ext.num_ptn = 0;
1139} 1139}
1140 1140
1141#if defined(USE_DISKLIST) 1141#if defined(USE_DISKLIST)
1142static void 1142static void
1143get_diskname(const char *fullname, char *diskname, size_t size) 1143get_diskname(const char *fullname, char *diskname, size_t size)
1144{ 1144{
1145 const char *p, *p2; 1145 const char *p, *p2;
1146 size_t len; 1146 size_t len;
1147 1147
1148 p = strrchr(fullname, '/'); 1148 p = strrchr(fullname, '/');
1149 if (p == NULL) 1149 if (p == NULL)
1150 p = fullname; 1150 p = fullname;
1151 else 1151 else
1152 p++; 1152 p++;
1153 1153
1154 if (*p == 0) { 1154 if (*p == 0) {
1155 strlcpy(diskname, fullname, size); 1155 strlcpy(diskname, fullname, size);
1156 return; 1156 return;
1157 } 1157 }
1158 1158
1159 if (*p == 'r') 1159 if (*p == 'r')
1160 p++; 1160 p++;
1161 1161
1162 for (p2 = p; *p2 != 0; p2++) 1162 for (p2 = p; *p2 != 0; p2++)
1163 if (isdigit((unsigned char)*p2)) 1163 if (isdigit((unsigned char)*p2))
1164 break; 1164 break;
1165 if (*p2 == 0) { 1165 if (*p2 == 0) {
1166 /* XXX invalid diskname? */ 1166 /* XXX invalid diskname? */
1167 strlcpy(diskname, fullname, size); 1167 strlcpy(diskname, fullname, size);
1168 return; 1168 return;
1169 } 1169 }
1170 while (isdigit((unsigned char)*p2)) 1170 while (isdigit((unsigned char)*p2))
1171 p2++;  1171 p2++;
1172 1172
1173 len = p2 - p; 1173 len = p2 - p;
1174 if (len > size) { 1174 if (len > size) {
1175 /* XXX */ 1175 /* XXX */
1176 strlcpy(diskname, fullname, size); 1176 strlcpy(diskname, fullname, size);
1177 return; 1177 return;
1178 } 1178 }
1179  1179
1180 memcpy(diskname, p, len); 1180 memcpy(diskname, p, len);
1181 diskname[len] = 0; 1181 diskname[len] = 0;
1182} 1182}
1183#endif 1183#endif
1184 1184
1185static void 1185static void
1186get_ptn_alignmemt(void) 1186get_ptn_alignmemt(void)
1187{ 1187{
1188 struct mbr_partition *partp = &mboot.mbr_parts[0]; 1188 struct mbr_partition *partp = &mboot.mbr_parts[0];
1189 uint32_t ptn_0_base, ptn_0_limit; 1189 uint32_t ptn_0_base, ptn_0_limit;
1190 1190
1191 /* Default to using 'traditional' cylinder alignment */ 1191 /* Default to using 'traditional' cylinder alignment */
1192 ptn_alignment = dos_cylindersectors; 1192 ptn_alignment = dos_cylindersectors;
1193 ptn_0_offset = dos_sectors; 1193 ptn_0_offset = dos_sectors;
1194 1194
1195 if (partp->mbrp_type != 0) { 1195 if (partp->mbrp_type != 0) {
1196 /* Try to copy alignment of first partition */ 1196 /* Try to copy alignment of first partition */
1197 ptn_0_base = le32toh(partp->mbrp_start); 1197 ptn_0_base = le32toh(partp->mbrp_start);
1198 ptn_0_limit = ptn_0_base + le32toh(partp->mbrp_size); 1198 ptn_0_limit = ptn_0_base + le32toh(partp->mbrp_size);
1199 if (!(ptn_0_limit & 2047)) { 1199 if (!(ptn_0_limit & 2047)) {
1200 /* Partition ends on a 1MB boundary, align to 1MB */ 1200 /* Partition ends on a 1MB boundary, align to 1MB */
1201 ptn_alignment = 2048; 1201 ptn_alignment = 2048;
1202 if (ptn_0_base <= 2048 1202 if (ptn_0_base <= 2048
1203 && !(ptn_0_base & (ptn_0_base - 1))) { 1203 && !(ptn_0_base & (ptn_0_base - 1))) {
1204 /* ptn_base is a power of 2, use it */ 1204 /* ptn_base is a power of 2, use it */
1205 ptn_0_offset = ptn_0_base; 1205 ptn_0_offset = ptn_0_base;
1206 } 1206 }
1207 } 1207 }
1208 } else { 1208 } else {
1209 /* Use 1MB alignment for large disks */ 1209 /* Use 1MB alignment for large disks */
1210 if (disksectors > 2048 * 1024 * 128) { 1210 if (disksectors > 2048 * 1024 * 128) {
1211 ptn_alignment = 2048; 1211 ptn_alignment = 2048;
1212 ptn_0_offset = 2048; 1212 ptn_0_offset = 2048;
1213 } 1213 }
1214 } 1214 }
1215} 1215}
1216 1216
1217static void 1217static void
1218get_bios_geometry(void) 1218get_bios_geometry(void)
1219{ 1219{
1220#if defined(USE_DISKLIST) 1220#if defined(USE_DISKLIST)
1221 int mib[2], i; 1221 int mib[2], i;
1222 size_t len; 1222 size_t len;
1223 struct biosdisk_info *bip; 1223 struct biosdisk_info *bip;
1224 struct nativedisk_info *nip; 1224 struct nativedisk_info *nip;
1225 char diskname[8]; 1225 char diskname[8];
1226 1226
1227 mib[0] = CTL_MACHDEP; 1227 mib[0] = CTL_MACHDEP;
1228 mib[1] = CPU_DISKINFO; 1228 mib[1] = CPU_DISKINFO;
1229 if (sysctl(mib, 2, NULL, &len, NULL, 0) < 0) { 1229 if (sysctl(mib, 2, NULL, &len, NULL, 0) < 0) {
1230 goto out; 1230 goto out;
1231 } 1231 }
1232 dl = (struct disklist *) malloc(len); 1232 dl = (struct disklist *) malloc(len);
1233 if (dl == NULL) 1233 if (dl == NULL)
1234 err(1, "Malloc failed"); 1234 err(1, "Malloc failed");
1235 if (sysctl(mib, 2, dl, &len, NULL, 0) < 0) { 1235 if (sysctl(mib, 2, dl, &len, NULL, 0) < 0) {
1236 free(dl); 1236 free(dl);
1237 dl = 0; 1237 dl = 0;
1238 goto out; 1238 goto out;
1239 } 1239 }
1240 1240
1241 get_diskname(disk, diskname, sizeof diskname); 1241 get_diskname(disk, diskname, sizeof diskname);
1242 1242
1243 for (i = 0; i < dl->dl_nnativedisks; i++) { 1243 for (i = 0; i < dl->dl_nnativedisks; i++) {
1244 nip = &dl->dl_nativedisks[i]; 1244 nip = &dl->dl_nativedisks[i];
1245 if (strcmp(diskname, nip->ni_devname)) 1245 if (strcmp(diskname, nip->ni_devname))
1246 continue; 1246 continue;
1247 /* 1247 /*
1248 * XXX listing possible matches is better. This is ok for 1248 * XXX listing possible matches is better. This is ok for
1249 * now because the user has a chance to change it later. 1249 * now because the user has a chance to change it later.
1250 * Also, if all the disks have the same parameters then we can 1250 * Also, if all the disks have the same parameters then we can
1251 * just use them, we don't need to know which disk is which. 1251 * just use them, we don't need to know which disk is which.
1252 */ 1252 */
1253 if (nip->ni_nmatches != 0) { 1253 if (nip->ni_nmatches != 0) {
1254 bip = &dl->dl_biosdisks[nip->ni_biosmatches[0]]; 1254 bip = &dl->dl_biosdisks[nip->ni_biosmatches[0]];
1255 dos_cylinders = bip->bi_cyl; 1255 dos_cylinders = bip->bi_cyl;
1256 dos_heads = bip->bi_head; 1256 dos_heads = bip->bi_head;
1257 dos_sectors = bip->bi_sec; 1257 dos_sectors = bip->bi_sec;
1258 if (bip->bi_lbasecs) 1258 if (bip->bi_lbasecs)
1259 dos_disksectors = bip->bi_lbasecs; 1259 dos_disksectors = bip->bi_lbasecs;
1260 return; 1260 return;
1261 } 1261 }
1262 } 1262 }
1263 out: 1263 out:
1264#endif 1264#endif
1265 /* Allright, allright, make a stupid guess.. */ 1265 /* Allright, allright, make a stupid guess.. */
1266 intuit_translated_geometry(); 1266 intuit_translated_geometry();
1267} 1267}
1268 1268
1269#ifdef BOOTSEL 1269#ifdef BOOTSEL
1270static daddr_t 1270static daddr_t
1271get_default_boot(void) 1271get_default_boot(void)
1272{ 1272{
1273 unsigned int id; 1273 unsigned int id;
1274 int p; 1274 int p;
1275 1275
1276 if (mboot.mbr_bootsel_magic != LE_MBR_BS_MAGIC) 1276 if (mboot.mbr_bootsel_magic != LE_MBR_BS_MAGIC)
1277 /* default to first active partition */ 1277 /* default to first active partition */
1278 return DEFAULT_ACTIVE; 1278 return DEFAULT_ACTIVE;
1279 1279
1280 id = mboot.mbr_bootsel.mbrbs_defkey; 1280 id = mboot.mbr_bootsel.mbrbs_defkey;
1281 1281
1282 if (mboot.mbr_bootsel.mbrbs_flags & MBR_BS_ASCII) { 1282 if (mboot.mbr_bootsel.mbrbs_flags & MBR_BS_ASCII) {
1283 /* Keycode is ascii */ 1283 /* Keycode is ascii */
1284 if (id == '\r') 1284 if (id == '\r')
1285 return DEFAULT_ACTIVE; 1285 return DEFAULT_ACTIVE;
1286 /* '1'+ => allocated partition id, 'a'+ => disk 0+ */ 1286 /* '1'+ => allocated partition id, 'a'+ => disk 0+ */
1287 if (id >= 'a' && id < 'a' + MAX_BIOS_DISKS) 1287 if (id >= 'a' && id < 'a' + MAX_BIOS_DISKS)
1288 return DEFAULT_DISK(id - 'a'); 1288 return DEFAULT_DISK(id - 'a');
1289 id -= '1'; 1289 id -= '1';
1290 } else { 1290 } else {
1291 /* keycode is PS/2 keycode */ 1291 /* keycode is PS/2 keycode */
1292 if (id == SCAN_ENTER) 1292 if (id == SCAN_ENTER)
1293 return DEFAULT_ACTIVE; 1293 return DEFAULT_ACTIVE;
1294 /* 1+ => allocated partition id, F1+ => disk 0+ */ 1294 /* 1+ => allocated partition id, F1+ => disk 0+ */
1295 if (id >= SCAN_F1 && id < SCAN_F1 + MAX_BIOS_DISKS) 1295 if (id >= SCAN_F1 && id < SCAN_F1 + MAX_BIOS_DISKS)
1296 return DEFAULT_DISK(id - SCAN_F1); 1296 return DEFAULT_DISK(id - SCAN_F1);
1297 id -= SCAN_1; 1297 id -= SCAN_1;
1298 } 1298 }
1299 1299
1300 /* Convert partition index to the invariant start sector number */ 1300 /* Convert partition index to the invariant start sector number */
1301 1301
1302 for (p = 0; p < MBR_PART_COUNT; p++) { 1302 for (p = 0; p < MBR_PART_COUNT; p++) {
1303 if (mboot.mbr_parts[p].mbrp_type == 0) 1303 if (mboot.mbr_parts[p].mbrp_type == 0)
1304 continue; 1304 continue;
1305 if (mboot.mbr_bootsel.mbrbs_nametab[p][0] == 0) 1305 if (mboot.mbr_bootsel.mbrbs_nametab[p][0] == 0)
1306 continue; 1306 continue;
1307 if (id-- == 0) 1307 if (id-- == 0)
1308 return le32toh(mboot.mbr_parts[p].mbrp_start); 1308 return le32toh(mboot.mbr_parts[p].mbrp_start);
1309 } 1309 }
1310 1310
1311 for (p = 0; p < ext.num_ptn; p++) { 1311 for (p = 0; p < ext.num_ptn; p++) {
1312 if (ext.ptn[p].mbr_parts[0].mbrp_type == 0) 1312 if (ext.ptn[p].mbr_parts[0].mbrp_type == 0)
1313 continue; 1313 continue;
1314 if (ext.ptn[p].mbr_bootsel.mbrbs_nametab[0][0] == 0) 1314 if (ext.ptn[p].mbr_bootsel.mbrbs_nametab[0][0] == 0)
1315 continue; 1315 continue;
1316 if (id-- == 0) 1316 if (id-- == 0)
1317 return ext_offset(p) 1317 return ext_offset(p)
1318 + le32toh(ext.ptn[p].mbr_parts[0].mbrp_start); 1318 + le32toh(ext.ptn[p].mbr_parts[0].mbrp_start);
1319 } 1319 }
1320 1320
1321 return DEFAULT_ACTIVE; 1321 return DEFAULT_ACTIVE;
1322} 1322}
1323 1323
1324static void 1324static void
1325set_default_boot(daddr_t default_ptn) 1325set_default_boot(daddr_t default_ptn)
1326{ 1326{
1327 int p; 1327 int p;
1328 static const unsigned char key_list[] = { SCAN_ENTER, SCAN_F1, SCAN_1, 1328 static const unsigned char key_list[] = { SCAN_ENTER, SCAN_F1, SCAN_1,
1329 '\r', 'a', '1' }; 1329 '\r', 'a', '1' };
1330 const unsigned char *key = key_list; 1330 const unsigned char *key = key_list;
1331 1331
1332 if (mboot.mbr_bootsel_magic != LE_MBR_BS_MAGIC) 1332 if (mboot.mbr_bootsel_magic != LE_MBR_BS_MAGIC)
1333 /* sanity */ 1333 /* sanity */
1334 return; 1334 return;
1335 1335
1336 if (mboot.mbr_bootsel.mbrbs_flags & MBR_BS_ASCII) 1336 if (mboot.mbr_bootsel.mbrbs_flags & MBR_BS_ASCII)
1337 /* Use ascii values */ 1337 /* Use ascii values */
1338 key += 3; 1338 key += 3;
1339 1339
1340 if (default_ptn == DEFAULT_ACTIVE) { 1340 if (default_ptn == DEFAULT_ACTIVE) {
1341 mboot.mbr_bootsel.mbrbs_defkey = key[0]; 1341 mboot.mbr_bootsel.mbrbs_defkey = key[0];
1342 return; 1342 return;
1343 } 1343 }
1344 1344
1345 if (default_ptn >= DEFAULT_DISK(0) 1345 if (default_ptn >= DEFAULT_DISK(0)
1346 && default_ptn < DEFAULT_DISK(MAX_BIOS_DISKS)) { 1346 && default_ptn < DEFAULT_DISK(MAX_BIOS_DISKS)) {
1347 mboot.mbr_bootsel.mbrbs_defkey = key[1] 1347 mboot.mbr_bootsel.mbrbs_defkey = key[1]
1348 + default_ptn - DEFAULT_DISK(0); 1348 + default_ptn - DEFAULT_DISK(0);
1349 return; 1349 return;
1350 } 1350 }
1351 1351
1352 mboot.mbr_bootsel.mbrbs_defkey = key[2]; 1352 mboot.mbr_bootsel.mbrbs_defkey = key[2];
1353 for (p = 0; p < MBR_PART_COUNT; p++) { 1353 for (p = 0; p < MBR_PART_COUNT; p++) {
1354 if (mboot.mbr_parts[p].mbrp_type == 0) 1354 if (mboot.mbr_parts[p].mbrp_type == 0)
1355 continue; 1355 continue;
1356 if (mboot.mbr_bootsel.mbrbs_nametab[p][0] == 0) 1356 if (mboot.mbr_bootsel.mbrbs_nametab[p][0] == 0)
1357 continue; 1357 continue;
1358 if (le32toh(mboot.mbr_parts[p].mbrp_start) == default_ptn) 1358 if (le32toh(mboot.mbr_parts[p].mbrp_start) == default_ptn)
1359 return; 1359 return;
1360 mboot.mbr_bootsel.mbrbs_defkey++; 1360 mboot.mbr_bootsel.mbrbs_defkey++;
1361 } 1361 }
1362 1362
1363 if (mboot.mbr_bootsel.mbrbs_flags & MBR_BS_EXTLBA) { 1363 if (mboot.mbr_bootsel.mbrbs_flags & MBR_BS_EXTLBA) {
1364 for (p = 0; p < ext.num_ptn; p++) { 1364 for (p = 0; p < ext.num_ptn; p++) {
1365 if (ext.ptn[p].mbr_parts[0].mbrp_type == 0) 1365 if (ext.ptn[p].mbr_parts[0].mbrp_type == 0)
1366 continue; 1366 continue;
1367 if (ext.ptn[p].mbr_bootsel.mbrbs_nametab[0][0] == 0) 1367 if (ext.ptn[p].mbr_bootsel.mbrbs_nametab[0][0] == 0)
1368 continue; 1368 continue;
1369 if (le32toh(ext.ptn[p].mbr_parts[0].mbrp_start) + 1369 if (le32toh(ext.ptn[p].mbr_parts[0].mbrp_start) +
1370 ext_offset(p) == default_ptn) 1370 ext_offset(p) == default_ptn)
1371 return; 1371 return;
1372 mboot.mbr_bootsel.mbrbs_defkey++; 1372 mboot.mbr_bootsel.mbrbs_defkey++;
1373 } 1373 }
1374 } 1374 }
1375 1375
1376 /* Default to first active partition */ 1376 /* Default to first active partition */
1377 mboot.mbr_bootsel.mbrbs_defkey = key[0]; 1377 mboot.mbr_bootsel.mbrbs_defkey = key[0];
1378} 1378}
1379 1379
1380static void 1380static void
1381install_bootsel(int needed) 1381install_bootsel(int needed)
1382{ 1382{
1383 struct mbr_bootsel *mbs = &mboot.mbr_bootsel; 1383 struct mbr_bootsel *mbs = &mboot.mbr_bootsel;
1384 int p; 1384 int p;
1385 int ext13 = 0; 1385 int ext13 = 0;
1386 const char *code; 1386 const char *code;
1387 1387
1388 needed |= MBR_BS_NEWMBR; /* need new bootsel code */ 1388 needed |= MBR_BS_NEWMBR; /* need new bootsel code */
1389 1389
1390 /* Work out which boot code we need for this configuration */ 1390 /* Work out which boot code we need for this configuration */
1391 for (p = 0; p < MBR_PART_COUNT; p++) { 1391 for (p = 0; p < MBR_PART_COUNT; p++) {
1392 if (mboot.mbr_parts[p].mbrp_type == 0) 1392 if (mboot.mbr_parts[p].mbrp_type == 0)
1393 continue; 1393 continue;
1394 if (mboot.mbr_bootsel_magic != LE_MBR_BS_MAGIC) 1394 if (mboot.mbr_bootsel_magic != LE_MBR_BS_MAGIC)
1395 break; 1395 break;
1396 if (mbs->mbrbs_nametab[p][0] == 0) 1396 if (mbs->mbrbs_nametab[p][0] == 0)
1397 continue; 1397 continue;
1398 needed |= MBR_BS_ACTIVE; 1398 needed |= MBR_BS_ACTIVE;
1399 if (le32toh(mboot.mbr_parts[p].mbrp_start) >= dos_totalsectors) 1399 if (le32toh(mboot.mbr_parts[p].mbrp_start) >= dos_totalsectors)
1400 ext13 = MBR_BS_EXTINT13; 1400 ext13 = MBR_BS_EXTINT13;
1401 } 1401 }
1402 1402
1403 for (p = 0; p < ext.num_ptn; p++) { 1403 for (p = 0; p < ext.num_ptn; p++) {
1404 if (ext.ptn[p].mbr_bootsel_magic != LE_MBR_BS_MAGIC) 1404 if (ext.ptn[p].mbr_bootsel_magic != LE_MBR_BS_MAGIC)
1405 continue; 1405 continue;
1406 if (ext.ptn[p].mbr_parts[0].mbrp_type == 0) 1406 if (ext.ptn[p].mbr_parts[0].mbrp_type == 0)
1407 continue; 1407 continue;
1408 if (ext.ptn[p].mbr_bootsel.mbrbs_nametab[p][0] == 0) 1408 if (ext.ptn[p].mbr_bootsel.mbrbs_nametab[p][0] == 0)
1409 continue; 1409 continue;
1410 needed |= MBR_BS_EXTLBA | MBR_BS_ACTIVE; 1410 needed |= MBR_BS_EXTLBA | MBR_BS_ACTIVE;
1411 } 1411 }
1412 1412
1413 if (B_flag) 1413 if (B_flag)
1414 needed |= MBR_BS_ACTIVE; 1414 needed |= MBR_BS_ACTIVE;
1415 1415
1416 /* Is the installed code good enough ? */ 1416 /* Is the installed code good enough ? */
1417 if (!i_flag && (needed == 0 || 1417 if (!i_flag && (needed == 0 ||
1418 (mboot.mbr_bootsel_magic == LE_MBR_BS_MAGIC 1418 (mboot.mbr_bootsel_magic == LE_MBR_BS_MAGIC
1419 && (mbs->mbrbs_flags & needed) == needed))) { 1419 && (mbs->mbrbs_flags & needed) == needed))) {
1420 /* yes - just set flags */ 1420 /* yes - just set flags */
1421 mbs->mbrbs_flags |= ext13; 1421 mbs->mbrbs_flags |= ext13;
1422 return; 1422 return;
1423 } 1423 }
1424 1424
1425 /* ok - we need to replace the bootcode */ 1425 /* ok - we need to replace the bootcode */
1426 1426
1427 if (f_flag && !(i_flag || B_flag)) { 1427 if (f_flag && !(i_flag || B_flag)) {
1428 warnx("Installed bootfile doesn't support required options."); 1428 warnx("Installed bootfile doesn't support required options.");
1429 return; 1429 return;
1430 } 1430 }
1431 1431
1432 if (!f_flag && bootsize == 0 && !i_flag) 1432 if (!f_flag && bootsize == 0 && !i_flag)
1433 /* Output an explanation for the 'update bootcode' prompt. */ 1433 /* Output an explanation for the 'update bootcode' prompt. */
1434 printf("\n%s\n", 1434 printf("\n%s\n",
1435 "Installed bootfile doesn't support required options."); 1435 "Installed bootfile doesn't support required options.");
1436 1436
1437 /* Were we told a specific file ? (which we have already read) */ 1437 /* Were we told a specific file ? (which we have already read) */
1438 /* If so check that it supports what we need. */ 1438 /* If so check that it supports what we need. */
1439 if (bootsize != 0 && needed != 0 1439 if (bootsize != 0 && needed != 0
1440 && (bootcode[0].mbr_bootsel_magic != LE_MBR_BS_MAGIC 1440 && (bootcode[0].mbr_bootsel_magic != LE_MBR_BS_MAGIC
1441 || ((bootcode[0].mbr_bootsel.mbrbs_flags & needed) != needed))) { 1441 || ((bootcode[0].mbr_bootsel.mbrbs_flags & needed) != needed))) {
1442 /* No it doesn't... */ 1442 /* No it doesn't... */
1443 if (f_flag) 1443 if (f_flag)
1444 warnx("Bootfile %s doesn't support " 1444 warnx("Bootfile %s doesn't support "
1445 "required bootsel options", boot_path ); 1445 "required bootsel options", boot_path );
1446 /* But install it anyway */ 1446 /* But install it anyway */
1447 else 1447 else
1448 if (yesno("Bootfile %s doesn't support the required " 1448 if (yesno("Bootfile %s doesn't support the required "
1449 "options,\ninstall default bootfile instead?", 1449 "options,\ninstall default bootfile instead?",
1450 boot_path)) 1450 boot_path))
1451 bootsize = 0; 1451 bootsize = 0;
1452 } 1452 }
1453 1453
1454 if (bootsize == 0) { 1454 if (bootsize == 0) {
1455 /* Get name of bootfile that supports the required facilities */ 1455 /* Get name of bootfile that supports the required facilities */
1456 code = DEFAULT_BOOTCODE; 1456 code = DEFAULT_BOOTCODE;
1457 if (needed & MBR_BS_ACTIVE) 1457 if (needed & MBR_BS_ACTIVE)
1458 code = DEFAULT_BOOTSELCODE; 1458 code = DEFAULT_BOOTSELCODE;
1459#ifdef DEFAULT_BOOTEXTCODE 1459#ifdef DEFAULT_BOOTEXTCODE
1460 if (needed & MBR_BS_EXTLBA) 1460 if (needed & MBR_BS_EXTLBA)
1461 code = DEFAULT_BOOTEXTCODE; 1461 code = DEFAULT_BOOTEXTCODE;
1462#endif 1462#endif
1463 1463
1464 bootsize = read_boot(code, bootcode, sizeof bootcode, 0); 1464 bootsize = read_boot(code, bootcode, sizeof bootcode, 0);
1465 if (bootsize == 0) 1465 if (bootsize == 0)
1466 /* The old bootcode is better than no bootcode at all */ 1466 /* The old bootcode is better than no bootcode at all */
1467 return; 1467 return;
1468 if ((bootcode[0].mbr_bootsel.mbrbs_flags & needed) != needed) 1468 if ((bootcode[0].mbr_bootsel.mbrbs_flags & needed) != needed)
1469 warnx("Default bootfile %s doesn't support required " 1469 warnx("Default bootfile %s doesn't support required "
1470 "options. Got flags 0x%x, wanted 0x%x\n", 1470 "options. Got flags 0x%x, wanted 0x%x\n",
1471 boot_path, bootcode[0].mbr_bootsel.mbrbs_flags, 1471 boot_path, bootcode[0].mbr_bootsel.mbrbs_flags,
1472 needed); 1472 needed);
1473 } 1473 }
1474 1474
1475 if (!f_flag && !yesno("Update the bootcode from %s?", boot_path)) 1475 if (!f_flag && !yesno("Update the bootcode from %s?", boot_path))
1476 return; 1476 return;
1477 1477
1478 init_sector0(0); 1478 init_sector0(0);
1479 1479
1480 if (mboot.mbr_bootsel_magic == LE_MBR_BS_MAGIC) 1480 if (mboot.mbr_bootsel_magic == LE_MBR_BS_MAGIC)
1481 mbs->mbrbs_flags = bootcode[0].mbr_bootsel.mbrbs_flags | ext13; 1481 mbs->mbrbs_flags = bootcode[0].mbr_bootsel.mbrbs_flags | ext13;
1482} 1482}
1483 1483
1484static daddr_t 1484static daddr_t
1485configure_bootsel(daddr_t default_ptn) 1485configure_bootsel(daddr_t default_ptn)
1486{ 1486{
1487 struct mbr_bootsel *mbs = &mboot.mbr_bootsel; 1487 struct mbr_bootsel *mbs = &mboot.mbr_bootsel;
1488 int i, item, opt; 1488 int i, item, opt;
1489 int tmo; 1489 int tmo;
1490 daddr_t *off; 1490 daddr_t *off;
1491 int num_bios_disks; 1491 int num_bios_disks;
1492 1492
1493#if defined(USE_DISKLIST) 1493#if defined(USE_DISKLIST)
1494 if (dl != NULL) { 1494 if (dl != NULL) {
1495 num_bios_disks = dl->dl_nbiosdisks; 1495 num_bios_disks = dl->dl_nbiosdisks;
1496 if (num_bios_disks > MAX_BIOS_DISKS) 1496 if (num_bios_disks > MAX_BIOS_DISKS)
1497 num_bios_disks = MAX_BIOS_DISKS; 1497 num_bios_disks = MAX_BIOS_DISKS;
1498 } else 1498 } else
1499#endif 1499#endif
1500 num_bios_disks = MAX_BIOS_DISKS; 1500 num_bios_disks = MAX_BIOS_DISKS;
1501 1501
1502 printf("\nBoot selector configuration:\n"); 1502 printf("\nBoot selector configuration:\n");
1503 1503
1504 /* The timeout value is in ticks, ~18.2 Hz. Avoid using floats. 1504 /* The timeout value is in ticks, ~18.2 Hz. Avoid using floats.
1505 * Ticks are nearly 64k/3600 - so our long timers are sligtly out! 1505 * Ticks are nearly 64k/3600 - so our long timers are sligtly out!
1506 * Newer bootcode always waits for 1 tick, so treats 0xffff 1506 * Newer bootcode always waits for 1 tick, so treats 0xffff
1507 * as wait forever. 1507 * as wait forever.
1508 */ 1508 */
1509 tmo = le16toh(mbs->mbrbs_timeo); 1509 tmo = le16toh(mbs->mbrbs_timeo);
1510 tmo = tmo == 0xffff ? -1 : (10 * tmo + 9) / 182; 1510 tmo = tmo == 0xffff ? -1 : (10 * tmo + 9) / 182;
1511 tmo = decimal("Timeout value (0 to 3600 seconds, -1 => never)", 1511 tmo = decimal("Timeout value (0 to 3600 seconds, -1 => never)",
1512 tmo, 0, -1, 3600); 1512 tmo, 0, -1, 3600);
1513 mbs->mbrbs_timeo = htole16(tmo == -1 ? 0xffff : (tmo * 182) / 10); 1513 mbs->mbrbs_timeo = htole16(tmo == -1 ? 0xffff : (tmo * 182) / 10);
1514 1514
1515 off = calloc(1 + MBR_PART_COUNT + ext.num_ptn + num_bios_disks, sizeof *off); 1515 off = calloc(1 + MBR_PART_COUNT + ext.num_ptn + num_bios_disks, sizeof *off);
1516 if (off == NULL) 1516 if (off == NULL)
1517 err(1, "Malloc failed"); 1517 err(1, "Malloc failed");
1518 1518
1519 printf("Select the default boot option. Options are:\n\n"); 1519 printf("Select the default boot option. Options are:\n\n");
1520 item = 0; 1520 item = 0;
1521 opt = 0; 1521 opt = 0;
1522 off[opt] = DEFAULT_ACTIVE; 1522 off[opt] = DEFAULT_ACTIVE;
1523 printf("%d: The first active partition\n", opt); 1523 printf("%d: The first active partition\n", opt);
1524 for (i = 0; i < MBR_PART_COUNT; i++) { 1524 for (i = 0; i < MBR_PART_COUNT; i++) {
1525 if (mboot.mbr_parts[i].mbrp_type == 0) 1525 if (mboot.mbr_parts[i].mbrp_type == 0)
1526 continue; 1526 continue;
1527 if (mbs->mbrbs_nametab[i][0] == 0) 1527 if (mbs->mbrbs_nametab[i][0] == 0)
1528 continue; 1528 continue;
1529 printf("%d: %s\n", ++opt, &mbs->mbrbs_nametab[i][0]); 1529 printf("%d: %s\n", ++opt, &mbs->mbrbs_nametab[i][0]);
1530 off[opt] = le32toh(mboot.mbr_parts[i].mbrp_start); 1530 off[opt] = le32toh(mboot.mbr_parts[i].mbrp_start);
1531 if (off[opt] == default_ptn) 1531 if (off[opt] == default_ptn)
1532 item = opt; 1532 item = opt;
1533 } 1533 }
1534 if (mbs->mbrbs_flags & MBR_BS_EXTLBA) { 1534 if (mbs->mbrbs_flags & MBR_BS_EXTLBA) {
1535 for (i = 0; i < ext.num_ptn; i++) { 1535 for (i = 0; i < ext.num_ptn; i++) {
1536 if (ext.ptn[i].mbr_parts[0].mbrp_type == 0) 1536 if (ext.ptn[i].mbr_parts[0].mbrp_type == 0)
1537 continue; 1537 continue;
1538 if (ext.ptn[i].mbr_bootsel.mbrbs_nametab[0][0] == 0) 1538 if (ext.ptn[i].mbr_bootsel.mbrbs_nametab[0][0] == 0)
1539 continue; 1539 continue;
1540 printf("%d: %s\n", 1540 printf("%d: %s\n",
1541 ++opt, ext.ptn[i].mbr_bootsel.mbrbs_nametab[0]); 1541 ++opt, ext.ptn[i].mbr_bootsel.mbrbs_nametab[0]);
1542 off[opt] = ext_offset(i) + 1542 off[opt] = ext_offset(i) +
1543 le32toh(ext.ptn[i].mbr_parts[0].mbrp_start); 1543 le32toh(ext.ptn[i].mbr_parts[0].mbrp_start);
1544 if (off[opt] == default_ptn) 1544 if (off[opt] == default_ptn)
1545 item = opt; 1545 item = opt;
1546 } 1546 }
1547 } 1547 }
1548 for (i = 0; i < num_bios_disks; i++) { 1548 for (i = 0; i < num_bios_disks; i++) {
1549 printf("%d: Harddisk %d\n", ++opt, i); 1549 printf("%d: Harddisk %d\n", ++opt, i);
1550 off[opt] = DEFAULT_DISK(i); 1550 off[opt] = DEFAULT_DISK(i);
1551 if (DEFAULT_DISK(i) == default_ptn) 1551 if (DEFAULT_DISK(i) == default_ptn)
1552 item = opt; 1552 item = opt;
1553 } 1553 }
1554 1554
1555 item = decimal("Default boot option", item, 0, 0, opt); 1555 item = decimal("Default boot option", item, 0, 0, opt);
1556 1556
1557 default_ptn = off[item]; 1557 default_ptn = off[item];
1558 free(off); 1558 free(off);
1559 return default_ptn; 1559 return default_ptn;
1560} 1560}
1561#endif /* BOOTSEL */ 1561#endif /* BOOTSEL */
1562 1562
1563 1563
1564/* Prerequisite: the disklabel parameters and master boot record must 1564/* Prerequisite: the disklabel parameters and master boot record must
1565 * have been read (i.e. dos_* and mboot are meaningful). 1565 * have been read (i.e. dos_* and mboot are meaningful).
1566 * Specification: modifies dos_cylinders, dos_heads, dos_sectors, and 1566 * Specification: modifies dos_cylinders, dos_heads, dos_sectors, and
1567 * dos_cylindersectors to be consistent with what the 1567 * dos_cylindersectors to be consistent with what the
1568 * partition table is using, if we can find a geometry 1568 * partition table is using, if we can find a geometry
1569 * which is consistent with all partition table entries. 1569 * which is consistent with all partition table entries.
1570 * We may get the number of cylinders slightly wrong (in 1570 * We may get the number of cylinders slightly wrong (in
1571 * the conservative direction). The idea is to be able 1571 * the conservative direction). The idea is to be able
1572 * to create a NetBSD partition on a disk we don't know 1572 * to create a NetBSD partition on a disk we don't know
1573 * the translated geometry of. 1573 * the translated geometry of.
1574 * This routine is only used for non-x86 systems or when we fail to 1574 * This routine is only used for non-x86 systems or when we fail to
1575 * get the BIOS geometry from the kernel. 1575 * get the BIOS geometry from the kernel.
1576 */ 1576 */
1577static void 1577static void
1578intuit_translated_geometry(void) 1578intuit_translated_geometry(void)
1579{ 1579{
1580 uint32_t xcylinders; 1580 uint32_t xcylinders;
1581 int xheads = -1, xsectors = -1, i, j; 1581 int xheads = -1, xsectors = -1, i, j;
1582 unsigned int c1, h1, s1, c2, h2, s2; 1582 unsigned int c1, h1, s1, c2, h2, s2;
1583 unsigned long a1, a2; 1583 unsigned long a1, a2;
1584 uint64_t num, denom; 1584 uint64_t num, denom;
1585 1585
1586 /* 1586 /*
1587 * The physical parameters may be invalid as bios geometry. 1587 * The physical parameters may be invalid as bios geometry.
1588 * If we cannot determine the actual bios geometry, we are 1588 * If we cannot determine the actual bios geometry, we are
1589 * better off picking a likely 'faked' geometry than leaving 1589 * better off picking a likely 'faked' geometry than leaving
1590 * the invalid physical one. 1590 * the invalid physical one.
1591 */ 1591 */
1592 1592
1593 if (dos_cylinders > MAXCYL || dos_heads > MAXHEAD || 1593 if (dos_cylinders > MAXCYL || dos_heads > MAXHEAD ||
1594 dos_sectors > MAXSECTOR) { 1594 dos_sectors > MAXSECTOR) {
1595 h1 = MAXHEAD - 1; 1595 h1 = MAXHEAD - 1;
1596 c1 = MAXCYL - 1; 1596 c1 = MAXCYL - 1;
1597#if defined(USE_DISKLIST) 1597#if defined(USE_DISKLIST)
1598 if (dl != NULL) { 1598 if (dl != NULL) {
1599 /* BIOS may use 256 heads or 1024 cylinders */ 1599 /* BIOS may use 256 heads or 1024 cylinders */
1600 for (i = 0; i < dl->dl_nbiosdisks; i++) { 1600 for (i = 0; i < dl->dl_nbiosdisks; i++) {
1601 if (h1 < (unsigned int)dl->dl_biosdisks[i].bi_head) 1601 if (h1 < (unsigned int)dl->dl_biosdisks[i].bi_head)
1602 h1 = dl->dl_biosdisks[i].bi_head; 1602 h1 = dl->dl_biosdisks[i].bi_head;
1603 if (c1 < (unsigned int)dl->dl_biosdisks[i].bi_cyl) 1603 if (c1 < (unsigned int)dl->dl_biosdisks[i].bi_cyl)
1604 c1 = dl->dl_biosdisks[i].bi_cyl; 1604 c1 = dl->dl_biosdisks[i].bi_cyl;
1605 } 1605 }
1606 } 1606 }