Sat Aug 27 17:16:01 2011 UTC ()
staticfy. __dead.


(joerg)
diff -r1.131 -r1.132 src/sbin/fdisk/fdisk.c

cvs diff -r1.131 -r1.132 src/sbin/fdisk/fdisk.c (switch to unified diff)

--- src/sbin/fdisk/fdisk.c 2011/05/08 14:22:16 1.131
+++ src/sbin/fdisk/fdisk.c 2011/08/27 17:16:01 1.132
@@ -1,2955 +1,2955 @@ @@ -1,2955 +1,2955 @@
1/* $NetBSD: fdisk.c,v 1.131 2011/05/08 14:22:16 pgoyette Exp $ */ 1/* $NetBSD: fdisk.c,v 1.132 2011/08/27 17:16:01 joerg 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.131 2011/05/08 14:22:16 pgoyette Exp $"); 42__RCSID("$NetBSD: fdisk.c,v 1.132 2011/08/27 17:16:01 joerg 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
143const char *disk = _PATH_DEFDISK; 143static const char *disk = _PATH_DEFDISK;
144 144
145struct disklabel disklabel; /* disk parameters */ 145static struct disklabel disklabel; /* disk parameters */
146 146
147struct mbr_sector mboot; 147static struct mbr_sector mboot;
148 148
149const char *boot_dir = DEFAULT_BOOTDIR; 149static const char *boot_dir = DEFAULT_BOOTDIR;
150char *boot_path = 0; /* 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 */
194unsigned int cylinders, sectors, heads; 194static unsigned int cylinders, sectors, heads;
195daddr_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 */
199unsigned int dos_cylinders; 199static unsigned int dos_cylinders;
200unsigned int dos_heads; 200static unsigned int dos_heads;
201unsigned int dos_sectors; 201static unsigned int dos_sectors;
202daddr_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
215int 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 */
218unsigned int ptn_alignment; /* default dos_cylindersectors */ 218static unsigned int ptn_alignment; /* default dos_cylindersectors */
219unsigned int ptn_0_offset; /* default dos_sectors */ 219static unsigned int ptn_0_offset; /* default dos_sectors */
220 220
221int fd = -1, wfd = -1, *rfd = &fd; 221static int fd = -1, wfd = -1, *rfd = &fd;
222char *disk_file = NULL; 222static char *disk_file = NULL;
223char *disk_type = NULL; 223static char *disk_type = NULL;
224 224
225int a_flag; /* set active partition */ 225static int a_flag; /* set active partition */
226int i_flag; /* init bootcode */ 226static int i_flag; /* init bootcode */
227int u_flag; /* update partition data */ 227static int u_flag; /* update partition data */
228int v_flag; /* more verbose */ 228static int v_flag; /* more verbose */
229int sh_flag; /* Output data as shell defines */ 229static int sh_flag; /* Output data as shell defines */
230int f_flag; /* force --not interactive */ 230static int f_flag; /* force --not interactive */
231int s_flag; /* set id,offset,size */ 231static int s_flag; /* set id,offset,size */
232int b_flag; /* Set cyl, heads, secs (as c/h/s) */ 232static int b_flag; /* Set cyl, heads, secs (as c/h/s) */
233int B_flag; /* Edit/install bootselect code */ 233static int B_flag; /* Edit/install bootselect code */
234int E_flag; /* extended partition number */ 234static int E_flag; /* extended partition number */
235int b_cyl, b_head, b_sec; /* b_flag values. */ 235static int b_cyl, b_head, b_sec; /* b_flag values. */
236 236
237#if !HAVE_NBTOOL_CONFIG_H 237#if !HAVE_NBTOOL_CONFIG_H
238int F_flag = 0; 238static int F_flag = 0;
239#else 239#else
240/* Tool - force 'file' mode to avoid unsupported functions and ioctls */ 240/* Tool - force 'file' mode to avoid unsupported functions and ioctls */
241int F_flag = 1; 241static int F_flag = 1;
242#endif 242#endif
243 243
244struct gpt_hdr gpt1, gpt2; /* GUID partition tables */ 244static struct gpt_hdr gpt1, gpt2; /* GUID partition tables */
245 245
246struct mbr_sector bootcode[8192 / sizeof (struct mbr_sector)]; 246static struct mbr_sector bootcode[8192 / sizeof (struct mbr_sector)];
247int bootsize; /* actual size of bootcode */ 247static int bootsize; /* actual size of bootcode */
248int boot_installed; /* 1 if we've copied code into the mbr */ 248static int boot_installed; /* 1 if we've copied code into the mbr */
249 249
250#if (defined(__i386__) || defined(__x86_64__)) && !HAVE_NBTOOL_CONFIG_H 250#if (defined(__i386__) || defined(__x86_64__)) && !HAVE_NBTOOL_CONFIG_H
251#define USE_DISKLIST 251#define USE_DISKLIST
252struct disklist *dl; 252static struct disklist *dl;
253#endif 253#endif
254 254
255 255
256#define KNOWN_SYSIDS (sizeof(mbr_ptypes)/sizeof(mbr_ptypes[0])) 256#define KNOWN_SYSIDS (sizeof(mbr_ptypes)/sizeof(mbr_ptypes[0]))
257 257
258void usage(void); 258__dead static void usage(void);
259void print_s0(int); 259static void print_s0(int);
260void print_part(struct mbr_sector *, int, daddr_t); 260static void print_part(struct mbr_sector *, int, daddr_t);
261void print_mbr_partition(struct mbr_sector *, int, daddr_t, daddr_t, int); 261static void print_mbr_partition(struct mbr_sector *, int, daddr_t, daddr_t, int);
262void print_pbr(daddr_t, int, uint8_t); 262static void print_pbr(daddr_t, int, uint8_t);
263int is_all_zero(const unsigned char *, size_t); 263static int is_all_zero(const unsigned char *, size_t);
264void printvis(int, const char *, const char *, size_t); 264static void printvis(int, const char *, const char *, size_t);
265int read_boot(const char *, void *, size_t, int); 265static int read_boot(const char *, void *, size_t, int);
266void init_sector0(int); 266static void init_sector0(int);
267void intuit_translated_geometry(void); 267static void intuit_translated_geometry(void);
268void get_bios_geometry(void); 268static void get_bios_geometry(void);
269void get_extended_ptn(void); 269static void get_extended_ptn(void);
270static void get_ptn_alignmemt(void); 270static static void get_ptn_alignmemt(void);
271#if defined(USE_DISKLIST) 271#if defined(USE_DISKLIST)
272void get_diskname(const char *, char *, size_t); 272static void get_diskname(const char *, char *, size_t);
273#endif 273#endif
274int change_part(int, int, int, daddr_t, daddr_t, char *); 274static int change_part(int, int, int, daddr_t, daddr_t, char *);
275void print_geometry(void); 275static void print_geometry(void);
276int first_active(void); 276static int first_active(void);
277void change_active(int); 277static void change_active(int);
278void change_bios_geometry(void); 278static void change_bios_geometry(void);
279void dos(int, unsigned char *, unsigned char *, unsigned char *); 279static void dos(int, unsigned char *, unsigned char *, unsigned char *);
280int open_disk(int); 280static int open_disk(int);
281int read_disk(daddr_t, void *); 281static int read_disk(daddr_t, void *);
282int write_disk(daddr_t, void *); 282static int write_disk(daddr_t, void *);
283int get_params(void); 283static int get_params(void);
284int read_s0(daddr_t, struct mbr_sector *); 284static int read_s0(daddr_t, struct mbr_sector *);
285int write_mbr(void); 285static int write_mbr(void);
286int read_gpt(daddr_t, struct gpt_hdr *); 286static int read_gpt(daddr_t, struct gpt_hdr *);
287int delete_gpt(struct gpt_hdr *); 287static int delete_gpt(struct gpt_hdr *);
288int yesno(const char *, ...); 288static int yesno(const char *, ...);
289int64_t decimal(const char *, int64_t, int, int64_t, int64_t); 289static int64_t decimal(const char *, int64_t, int, int64_t, int64_t);
290#define DEC_SEC 1 /* asking for a sector number */ 290#define DEC_SEC 1 /* asking for a sector number */
291#define DEC_RND 2 /* round to end of first track */ 291#define DEC_RND 2 /* round to end of first track */
292#define DEC_RND_0 4 /* convert 0 to size of a track */ 292#define DEC_RND_0 4 /* convert 0 to size of a track */
293#define DEC_RND_DOWN 8 /* subtract 1 track */ 293#define DEC_RND_DOWN 8 /* subtract 1 track */
294#define DEC_RND_DOWN_2 16 /* subtract 2 tracks */ 294#define DEC_RND_DOWN_2 16 /* subtract 2 tracks */
295void string(const char *, int, char *); 295static void string(const char *, int, char *);
296int ptn_id(const char *, int *); 296static int ptn_id(const char *, int *);
297int type_match(const void *, const void *); 297static int type_match(const void *, const void *);
298const char *get_type(int); 298static const char *get_type(int);
299int 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
301daddr_t configure_bootsel(daddr_t); 301static daddr_t configure_bootsel(daddr_t);
302void install_bootsel(int); 302static void install_bootsel(int);
303daddr_t get_default_boot(void); 303static daddr_t get_default_boot(void);
304void set_default_boot(daddr_t); 304static void set_default_boot(daddr_t);
305#endif 305#endif
306 306
307static void 307static void
308initvar_disk(const char **diskp) 308initvar_disk(const char **diskp)
309{ 309{
310#if !HAVE_NBTOOL_CONFIG_H 310#if !HAVE_NBTOOL_CONFIG_H
311 int mib[2]; 311 int mib[2];
312 size_t len; 312 size_t len;
313 char *root_device; 313 char *root_device;
314 314
315 mib[0] = CTL_KERN; 315 mib[0] = CTL_KERN;
316 mib[1] = KERN_ROOT_DEVICE; 316 mib[1] = KERN_ROOT_DEVICE;
317 if (sysctl(mib, 2, NULL, &len, NULL, 0) == -1 || 317 if (sysctl(mib, 2, NULL, &len, NULL, 0) == -1 ||
318 (root_device = malloc(len)) == NULL || 318 (root_device = malloc(len)) == NULL ||
319 sysctl(mib, 2, root_device, &len, NULL, 0) == -1) 319 sysctl(mib, 2, root_device, &len, NULL, 0) == -1)
320 return; 320 return;
321 321
322 *diskp = root_device; 322 *diskp = root_device;
323#endif /* HAVE_NBTOOL_CONFIG_H */ 323#endif /* HAVE_NBTOOL_CONFIG_H */
324} 324}
325 325
326int 326int
327main(int argc, char *argv[]) 327main(int argc, char *argv[])
328{ 328{
329 struct stat sb; 329 struct stat sb;
330 int ch; 330 int ch;
331 size_t len; 331 size_t len;
332 char *cp; 332 char *cp;
333 int n; 333 int n;
334#ifdef BOOTSEL 334#ifdef BOOTSEL
335 daddr_t default_ptn; /* start sector of default ptn */ 335 daddr_t default_ptn; /* start sector of default ptn */
336 char *cbootmenu = 0; 336 char *cbootmenu = 0;
337#endif 337#endif
338 338
339 int csysid; /* For the s_flag. */ 339 int csysid; /* For the s_flag. */
340 unsigned int cstart, csize; 340 unsigned int cstart, csize;
341 a_flag = u_flag = sh_flag = f_flag = s_flag = b_flag = 0; 341 a_flag = u_flag = sh_flag = f_flag = s_flag = b_flag = 0;
342 i_flag = B_flag = 0; 342 i_flag = B_flag = 0;
343 v_flag = 0; 343 v_flag = 0;
344 E_flag = 0; 344 E_flag = 0;
345 csysid = cstart = csize = 0; 345 csysid = cstart = csize = 0;
346 while ((ch = getopt(argc, argv, OPTIONS)) != -1) { 346 while ((ch = getopt(argc, argv, OPTIONS)) != -1) {
347 switch (ch) { 347 switch (ch) {
348 case '0': 348 case '0':
349 partition = 0; 349 partition = 0;
350 break; 350 break;
351 case '1': 351 case '1':
352 partition = 1; 352 partition = 1;
353 break; 353 break;
354 case '2': 354 case '2':
355 partition = 2; 355 partition = 2;
356 break; 356 break;
357 case '3': 357 case '3':
358 partition = 3; 358 partition = 3;
359 break; 359 break;
360 case 'E': /* Extended partition number */ 360 case 'E': /* Extended partition number */
361 E_flag = 1; 361 E_flag = 1;
362 partition = strtoul(optarg, &cp, 0); 362 partition = strtoul(optarg, &cp, 0);
363 if (*cp || partition < 0) 363 if (*cp || partition < 0)
364 errx(1, "Bad partition number -E %s.", optarg); 364 errx(1, "Bad partition number -E %s.", optarg);
365 break; 365 break;
366#ifdef BOOTSEL 366#ifdef BOOTSEL
367 case 'B': /* Bootselect parameters */ 367 case 'B': /* Bootselect parameters */
368 B_flag = 1; 368 B_flag = 1;
369 break; 369 break;
370#endif 370#endif
371 case 'F': /* device argument is really a file */ 371 case 'F': /* device argument is really a file */
372 F_flag = 1; 372 F_flag = 1;
373 break; 373 break;
374 case 'S': /* Output as shell variables */ 374 case 'S': /* Output as shell variables */
375 sh_flag = 1; 375 sh_flag = 1;
376 break; 376 break;
377 case 'a': /* Set active partition */ 377 case 'a': /* Set active partition */
378 a_flag = 1; 378 a_flag = 1;
379 break; 379 break;
380 case 'f': /* Non interactive */ 380 case 'f': /* Non interactive */
381 f_flag = 1; 381 f_flag = 1;
382 break; 382 break;
383 case 'i': /* Always update bootcode */ 383 case 'i': /* Always update bootcode */
384 i_flag = 1; 384 i_flag = 1;
385 break; 385 break;
386 case 'l': /* List known partition types */ 386 case 'l': /* List known partition types */
387 for (len = 0; len < KNOWN_SYSIDS; len++) 387 for (len = 0; len < KNOWN_SYSIDS; len++)
388 printf("%03d %s\n", mbr_ptypes[len].id, 388 printf("%03d %s\n", mbr_ptypes[len].id,
389 mbr_ptypes[len].name); 389 mbr_ptypes[len].name);
390 return 0; 390 return 0;
391 case 'u': /* Update partition details */ 391 case 'u': /* Update partition details */
392 u_flag = 1; 392 u_flag = 1;
393 break; 393 break;
394 case 'v': /* Be verbose */ 394 case 'v': /* Be verbose */
395 v_flag++; 395 v_flag++;
396 break; 396 break;
397 case 's': /* Partition details */ 397 case 's': /* Partition details */
398 s_flag = 1; 398 s_flag = 1;
399 if (sscanf(optarg, "%d/%u/%u%n", &csysid, &cstart, 399 if (sscanf(optarg, "%d/%u/%u%n", &csysid, &cstart,
400 &csize, &n) == 3) { 400 &csize, &n) == 3) {
401 if (optarg[n] == 0) 401 if (optarg[n] == 0)
402 break; 402 break;
403#ifdef BOOTSEL 403#ifdef BOOTSEL
404 if (optarg[n] == '/') { 404 if (optarg[n] == '/') {
405 cbootmenu = optarg + n + 1; 405 cbootmenu = optarg + n + 1;
406 break; 406 break;
407 } 407 }
408#endif 408#endif
409 } 409 }
410 errx(1, "Bad argument to the -s flag."); 410 errx(1, "Bad argument to the -s flag.");
411 break; 411 break;
412 case 'b': /* BIOS geometry */ 412 case 'b': /* BIOS geometry */
413 b_flag = 1; 413 b_flag = 1;
414 if (sscanf(optarg, "%d/%d/%d%n", &b_cyl, &b_head, 414 if (sscanf(optarg, "%d/%d/%d%n", &b_cyl, &b_head,
415 &b_sec, &n) != 3 || optarg[n] != 0) 415 &b_sec, &n) != 3 || optarg[n] != 0)
416 errx(1, "Bad argument to the -b flag."); 416 errx(1, "Bad argument to the -b flag.");
417 if (b_cyl > MAXCYL) 417 if (b_cyl > MAXCYL)
418 b_cyl = MAXCYL; 418 b_cyl = MAXCYL;
419 break; 419 break;
420 case 'A': /* Partition alignment[/offset] */ 420 case 'A': /* Partition alignment[/offset] */
421 if (sscanf(optarg, "%u%n/%u%n", &ptn_alignment, 421 if (sscanf(optarg, "%u%n/%u%n", &ptn_alignment,
422 &n, &ptn_0_offset, &n) < 1 422 &n, &ptn_0_offset, &n) < 1
423 || optarg[n] != 0 423 || optarg[n] != 0
424 || ptn_0_offset > ptn_alignment) 424 || ptn_0_offset > ptn_alignment)
425 errx(1, "Bad argument to the -A flag."); 425 errx(1, "Bad argument to the -A flag.");
426 if (ptn_0_offset == 0) 426 if (ptn_0_offset == 0)
427 ptn_0_offset = ptn_alignment; 427 ptn_0_offset = ptn_alignment;
428 break; 428 break;
429 case 'c': /* file/directory containing boot code */ 429 case 'c': /* file/directory containing boot code */
430 if (strchr(optarg, '/') != NULL && 430 if (strchr(optarg, '/') != NULL &&
431 stat(optarg, &sb) == 0 && 431 stat(optarg, &sb) == 0 &&
432 (sb.st_mode & S_IFMT) == S_IFDIR) { 432 (sb.st_mode & S_IFMT) == S_IFDIR) {
433 boot_dir = optarg; 433 boot_dir = optarg;
434 break; 434 break;
435 } 435 }
436 bootsize = read_boot(optarg, bootcode, 436 bootsize = read_boot(optarg, bootcode,
437 sizeof bootcode, 1); 437 sizeof bootcode, 1);
438 i_flag = 1; 438 i_flag = 1;
439 break; 439 break;
440 case 'r': /* read data from disk_file (not raw disk) */ 440 case 'r': /* read data from disk_file (not raw disk) */
441 rfd = &wfd; 441 rfd = &wfd;
442 /* FALLTHROUGH */ 442 /* FALLTHROUGH */
443 case 'w': /* write data to disk_file */ 443 case 'w': /* write data to disk_file */
444 disk_file = optarg; 444 disk_file = optarg;
445 break; 445 break;
446 case 't': 446 case 't':
447 if (setdisktab(optarg) == -1) 447 if (setdisktab(optarg) == -1)
448 errx(EXIT_FAILURE, "bad disktab"); 448 errx(EXIT_FAILURE, "bad disktab");
449 break; 449 break;
450 case 'T': 450 case 'T':
451 disk_type = optarg; 451 disk_type = optarg;
452 break; 452 break;
453 default: 453 default:
454 usage(); 454 usage();
455 } 455 }
456 } 456 }
457 argc -= optind; 457 argc -= optind;
458 argv += optind; 458 argv += optind;
459 459
460 if (disk_type != NULL && getdiskbyname(disk_type) == NULL) 460 if (disk_type != NULL && getdiskbyname(disk_type) == NULL)
461 errx(EXIT_FAILURE, "bad disktype"); 461 errx(EXIT_FAILURE, "bad disktype");
462 462
463 if (sh_flag && (a_flag || i_flag || u_flag || f_flag || s_flag)) 463 if (sh_flag && (a_flag || i_flag || u_flag || f_flag || s_flag))
464 usage(); 464 usage();
465 465
466 if (B_flag && f_flag) { 466 if (B_flag && f_flag) {
467 warnx("Bootselector may only be configured interactively"); 467 warnx("Bootselector may only be configured interactively");
468 usage(); 468 usage();
469 } 469 }
470 470
471 if (f_flag && u_flag && !s_flag) { 471 if (f_flag && u_flag && !s_flag) {
472 warnx("Partition data not specified"); 472 warnx("Partition data not specified");
473 usage(); 473 usage();
474 } 474 }
475 475
476 if (s_flag && partition == -1) { 476 if (s_flag && partition == -1) {
477 warnx("-s flag requires a partition selected."); 477 warnx("-s flag requires a partition selected.");
478 usage(); 478 usage();
479 } 479 }
480 480
481 if (argc > 1) 481 if (argc > 1)
482 usage(); 482 usage();
483 483
484 if (argc > 0) 484 if (argc > 0)
485 disk = argv[0]; 485 disk = argv[0];
486 else if (!F_flag) { 486 else if (!F_flag) {
487 /* Default to boot device */ 487 /* Default to boot device */
488 initvar_disk(&disk); 488 initvar_disk(&disk);
489 } 489 }
490 490
491 if (!F_flag && stat(disk, &sb) == 0 && S_ISREG(sb.st_mode)) 491 if (!F_flag && stat(disk, &sb) == 0 && S_ISREG(sb.st_mode))
492 F_flag = 1; 492 F_flag = 1;
493 493
494 if (open_disk(B_flag || a_flag || i_flag || u_flag) < 0) 494 if (open_disk(B_flag || a_flag || i_flag || u_flag) < 0)
495 exit(1); 495 exit(1);
496 496
497 if (read_s0(0, &mboot)) 497 if (read_s0(0, &mboot))
498 /* must have been a blank disk */ 498 /* must have been a blank disk */
499 init_sector0(1); 499 init_sector0(1);
500 500
501 read_gpt(GPT_HDR_BLKNO, &gpt1); 501 read_gpt(GPT_HDR_BLKNO, &gpt1);
502 read_gpt(disksectors - 1, &gpt2); 502 read_gpt(disksectors - 1, &gpt2);
503 503
504 if (b_flag) { 504 if (b_flag) {
505 dos_cylinders = b_cyl; 505 dos_cylinders = b_cyl;
506 dos_heads = b_head; 506 dos_heads = b_head;
507 dos_sectors = b_sec; 507 dos_sectors = b_sec;
508 } else { 508 } else {
509 get_bios_geometry(); 509 get_bios_geometry();
510 } 510 }
511 511
512 if (ptn_alignment == 0) 512 if (ptn_alignment == 0)
513 get_ptn_alignmemt(); 513 get_ptn_alignmemt();
514 514
515 get_extended_ptn(); 515 get_extended_ptn();
516 516
517#ifdef BOOTSEL 517#ifdef BOOTSEL
518 default_ptn = get_default_boot(); 518 default_ptn = get_default_boot();
519#endif 519#endif
520 520
521 if (E_flag && !u_flag && partition >= ext.num_ptn) 521 if (E_flag && !u_flag && partition >= ext.num_ptn)
522 errx(1, "Extended partition %d is not defined.", partition); 522 errx(1, "Extended partition %d is not defined.", partition);
523 523
524 /* Do the update stuff! */ 524 /* Do the update stuff! */
525 if (u_flag) { 525 if (u_flag) {
526 if (!f_flag && !b_flag) 526 if (!f_flag && !b_flag)
527 change_bios_geometry(); 527 change_bios_geometry();
528 528
529 if (s_flag) 529 if (s_flag)
530 change_part(E_flag, partition, csysid, cstart, csize, 530 change_part(E_flag, partition, csysid, cstart, csize,
531 cbootmenu); 531 cbootmenu);
532 else { 532 else {
533 int part = partition, chg_ext = E_flag, prompt = 1; 533 int part = partition, chg_ext = E_flag, prompt = 1;
534 do { 534 do {
535 if (prompt) { 535 if (prompt) {
536 printf("\n"); 536 printf("\n");
537 print_s0(partition); 537 print_s0(partition);
538 } 538 }
539 if (partition == -1) 539 if (partition == -1)
540 part = ptn_id( 540 part = ptn_id(
541 "Which partition do you want to change?", 541 "Which partition do you want to change?",
542 &chg_ext); 542 &chg_ext);
543 if (part < 0) 543 if (part < 0)
544 break; 544 break;
545 prompt = change_part(chg_ext, part, 0, 0, 0, 0); 545 prompt = change_part(chg_ext, part, 0, 0, 0, 0);
546 } while (partition == -1); 546 } while (partition == -1);
547 } 547 }
548 } else { 548 } else {
549 if (!i_flag && !B_flag) { 549 if (!i_flag && !B_flag) {
550 print_geometry(); 550 print_geometry();
551 print_s0(partition); 551 print_s0(partition);
552 } 552 }
553 } 553 }
554 554
555 if (a_flag && !E_flag) 555 if (a_flag && !E_flag)
556 change_active(partition); 556 change_active(partition);
557 557
558#ifdef BOOTSEL 558#ifdef BOOTSEL
559 if (B_flag || u_flag || i_flag) 559 if (B_flag || u_flag || i_flag)
560 /* Ensure the mbr code supports this configuration */ 560 /* Ensure the mbr code supports this configuration */
561 install_bootsel(0); 561 install_bootsel(0);
562 if (B_flag) 562 if (B_flag)
563 default_ptn = configure_bootsel(default_ptn); 563 default_ptn = configure_bootsel(default_ptn);
564 set_default_boot(default_ptn); 564 set_default_boot(default_ptn);
565#else 565#else
566 if (i_flag) 566 if (i_flag)
567 init_sector0(0); 567 init_sector0(0);
568#endif 568#endif
569 569
570 if (u_flag || a_flag || i_flag || B_flag) { 570 if (u_flag || a_flag || i_flag || B_flag) {
571 if (!f_flag) { 571 if (!f_flag) {
572 printf("\nWe haven't written the MBR back to disk " 572 printf("\nWe haven't written the MBR back to disk "
573 "yet. This is your last chance.\n"); 573 "yet. This is your last chance.\n");
574 if (u_flag) 574 if (u_flag)
575 print_s0(-1); 575 print_s0(-1);
576 if (gpt1.hdr_size != 0 || gpt2.hdr_size != 0) 576 if (gpt1.hdr_size != 0 || gpt2.hdr_size != 0)
577 printf("\nWARNING: The disk is carrying " 577 printf("\nWARNING: The disk is carrying "
578 "GUID Partition Tables.\n" 578 "GUID Partition Tables.\n"
579 " If you continue, " 579 " If you continue, "
580 "GPT headers will be deleted.\n\n"); 580 "GPT headers will be deleted.\n\n");
581 if (yesno("Should we write new partition table?")) { 581 if (yesno("Should we write new partition table?")) {
582 delete_gpt(&gpt1); 582 delete_gpt(&gpt1);
583 delete_gpt(&gpt2); 583 delete_gpt(&gpt2);
584 write_mbr(); 584 write_mbr();
585 } 585 }
586 } else { 586 } else {
587 if (delete_gpt(&gpt1) > 0) 587 if (delete_gpt(&gpt1) > 0)
588 warnx("Primary GPT header was deleted"); 588 warnx("Primary GPT header was deleted");
589 if (delete_gpt(&gpt2) > 0) 589 if (delete_gpt(&gpt2) > 0)
590 warnx("Secondary GPT header was deleted"); 590 warnx("Secondary GPT header was deleted");
591 write_mbr(); 591 write_mbr();
592 } 592 }
593 } 593 }
594 594
595 exit(0); 595 exit(0);
596} 596}
597 597
598void 598static void
599usage(void) 599usage(void)
600{ 600{
601 int indent = 7 + (int)strlen(getprogname()) + 1; 601 int indent = 7 + (int)strlen(getprogname()) + 1;
602 602
603 (void)fprintf(stderr, "usage: %s [-afiluvBS] " 603 (void)fprintf(stderr, "usage: %s [-afiluvBS] "
604 "[-A ptn_alignment[/ptn_0_offset]] \\\n" 604 "[-A ptn_alignment[/ptn_0_offset]] \\\n"
605 "%*s[-b cylinders/heads/sectors] \\\n" 605 "%*s[-b cylinders/heads/sectors] \\\n"
606 "%*s[-0123 | -E num " 606 "%*s[-0123 | -E num "
607 "[-s id/start/size[/bootmenu]]] \\\n" 607 "[-s id/start/size[/bootmenu]]] \\\n"
608 "%*s[-t disktab] [-T disktype] \\\n" 608 "%*s[-t disktab] [-T disktype] \\\n"
609 "%*s[-c bootcode] " 609 "%*s[-c bootcode] "
610 "[-r|-w file] [device]\n" 610 "[-r|-w file] [device]\n"
611 "\t-a change active partition\n" 611 "\t-a change active partition\n"
612 "\t-f force - not interactive\n" 612 "\t-f force - not interactive\n"
613 "\t-i initialise MBR code\n" 613 "\t-i initialise MBR code\n"
614 "\t-l list partition types\n" 614 "\t-l list partition types\n"
615 "\t-u update partition data\n" 615 "\t-u update partition data\n"
616 "\t-v verbose output, -v -v more verbose still\n" 616 "\t-v verbose output, -v -v more verbose still\n"
617 "\t-B update bootselect options\n" 617 "\t-B update bootselect options\n"
618 "\t-F treat device as a regular file\n" 618 "\t-F treat device as a regular file\n"
619 "\t-S output as shell defines\n" 619 "\t-S output as shell defines\n"
620 "\t-r and -w access 'file' for non-destructive testing\n", 620 "\t-r and -w access 'file' for non-destructive testing\n",
621 getprogname(), indent, "", indent, "", indent, "", indent, ""); 621 getprogname(), indent, "", indent, "", indent, "", indent, "");
622 exit(1); 622 exit(1);
623} 623}
624 624
625static daddr_t 625static daddr_t
626ext_offset(int part) 626ext_offset(int part)
627{ 627{
628 daddr_t offset = ext.base; 628 daddr_t offset = ext.base;
629 629
630 if (part != 0) 630 if (part != 0)
631 offset += le32toh(ext.ptn[part - 1].mbr_parts[1].mbrp_start); 631 offset += le32toh(ext.ptn[part - 1].mbr_parts[1].mbrp_start);
632 return offset; 632 return offset;
633} 633}
634 634
635void 635static void
636print_s0(int which) 636print_s0(int which)
637{ 637{
638 int part; 638 int part;
639 639
640 if (which == -1) { 640 if (which == -1) {
641 if (!sh_flag) 641 if (!sh_flag)
642 printf("Partition table:\n"); 642 printf("Partition table:\n");
643 for (part = 0; part < MBR_PART_COUNT; part++) { 643 for (part = 0; part < MBR_PART_COUNT; part++) {
644 if (!sh_flag) 644 if (!sh_flag)
645 printf("%d: ", part); 645 printf("%d: ", part);
646 print_part(&mboot, part, 0); 646 print_part(&mboot, part, 0);
647 } 647 }
648 if (!sh_flag) { 648 if (!sh_flag) {
649 if (ext.is_corrupt) 649 if (ext.is_corrupt)
650 printf("Extended partition table is corrupt\n"); 650 printf("Extended partition table is corrupt\n");
651 else 651 else
652 if (ext.num_ptn != 0) 652 if (ext.num_ptn != 0)
653 printf("Extended partition table:\n"); 653 printf("Extended partition table:\n");
654 } 654 }
655 for (part = 0; part < ext.num_ptn; part++) { 655 for (part = 0; part < ext.num_ptn; part++) {
656 if (!sh_flag) 656 if (!sh_flag)
657 printf("E%d: ", part); 657 printf("E%d: ", part);
658 print_part(&ext.ptn[part], 0, ext_offset(part)); 658 print_part(&ext.ptn[part], 0, ext_offset(part));
659 if (!sh_flag && v_flag >= 2) { 659 if (!sh_flag && v_flag >= 2) {
660 printf("link: "); 660 printf("link: ");
661 print_mbr_partition(&ext.ptn[part], 1, 661 print_mbr_partition(&ext.ptn[part], 1,
662 ext_offset(part), ext.base, 0); 662 ext_offset(part), ext.base, 0);
663 } 663 }
664 } 664 }
665#ifdef BOOTSEL 665#ifdef BOOTSEL
666 if (!sh_flag && mboot.mbr_bootsel_magic == LE_MBR_BS_MAGIC) { 666 if (!sh_flag && mboot.mbr_bootsel_magic == LE_MBR_BS_MAGIC) {
667 int tmo; 667 int tmo;
668 668
669 printf("Bootselector "); 669 printf("Bootselector ");
670 if (mboot.mbr_bootsel.mbrbs_flags & MBR_BS_ACTIVE) { 670 if (mboot.mbr_bootsel.mbrbs_flags & MBR_BS_ACTIVE) {
671 printf("enabled"); 671 printf("enabled");
672 tmo = le16toh(mboot.mbr_bootsel.mbrbs_timeo); 672 tmo = le16toh(mboot.mbr_bootsel.mbrbs_timeo);
673 if (tmo == 0xffff) 673 if (tmo == 0xffff)
674 printf(", infinite timeout"); 674 printf(", infinite timeout");
675 else 675 else
676 printf(", timeout %d seconds", 676 printf(", timeout %d seconds",
677 (10 * tmo + 9) / 182); 677 (10 * tmo + 9) / 182);
678 } else 678 } else
679 printf("disabled"); 679 printf("disabled");
680 printf(".\n"); 680 printf(".\n");
681 } 681 }
682#endif 682#endif
683 if (!sh_flag) { 683 if (!sh_flag) {
684 int active = first_active(); 684 int active = first_active();
685 if (active == MBR_PART_COUNT) 685 if (active == MBR_PART_COUNT)
686 printf("No active partition.\n"); 686 printf("No active partition.\n");
687 else 687 else
688 printf("First active partition: %d\n", active); 688 printf("First active partition: %d\n", active);
689 } 689 }
690 if (!sh_flag && mboot.mbr_dsn != 0) 690 if (!sh_flag && mboot.mbr_dsn != 0)
691 printf("Drive serial number: %"PRIu32" (0x%08x)\n", 691 printf("Drive serial number: %"PRIu32" (0x%08x)\n",
692 le32toh(mboot.mbr_dsn), 692 le32toh(mboot.mbr_dsn),
693 le32toh(mboot.mbr_dsn)); 693 le32toh(mboot.mbr_dsn));
694 return; 694 return;
695 } 695 }
696 696
697 if (E_flag) { 697 if (E_flag) {
698 if (!sh_flag) 698 if (!sh_flag)
699 printf("Extended partition E%d:\n", which); 699 printf("Extended partition E%d:\n", which);
700 if (which > ext.num_ptn) 700 if (which > ext.num_ptn)
701 printf("Undefined\n"); 701 printf("Undefined\n");
702 else 702 else
703 print_part(&ext.ptn[which], 0, ext_offset(which)); 703 print_part(&ext.ptn[which], 0, ext_offset(which));
704 } else { 704 } else {
705 if (!sh_flag) 705 if (!sh_flag)
706 printf("Partition %d:\n", which); 706 printf("Partition %d:\n", which);
707 print_part(&mboot, which, 0); 707 print_part(&mboot, which, 0);
708 } 708 }
709} 709}
710 710
711void 711static void
712print_part(struct mbr_sector *boot, int part, daddr_t offset) 712print_part(struct mbr_sector *boot, int part, daddr_t offset)
713{ 713{
714 struct mbr_partition *partp; 714 struct mbr_partition *partp;
715 const char *e; 715 const char *e;
716 716
717 if (!sh_flag) { 717 if (!sh_flag) {
718 print_mbr_partition(boot, part, offset, 0, 0); 718 print_mbr_partition(boot, part, offset, 0, 0);
719 return; 719 return;
720 } 720 }
721 721
722 partp = &boot->mbr_parts[part]; 722 partp = &boot->mbr_parts[part];
723 if (boot != &mboot) { 723 if (boot != &mboot) {
724 part = boot - ext.ptn; 724 part = boot - ext.ptn;
725 e = "E"; 725 e = "E";
726 } else 726 } else
727 e = ""; 727 e = "";
728 728
729 if (partp->mbrp_type == 0) { 729 if (partp->mbrp_type == 0) {
730 printf("PART%s%dSIZE=0\n", e, part); 730 printf("PART%s%dSIZE=0\n", e, part);
731 return; 731 return;
732 } 732 }
733 733
734 printf("PART%s%dID=%d\n", e, part, partp->mbrp_type); 734 printf("PART%s%dID=%d\n", e, part, partp->mbrp_type);
735 printf("PART%s%dSIZE=%u\n", e, part, le32toh(partp->mbrp_size)); 735 printf("PART%s%dSIZE=%u\n", e, part, le32toh(partp->mbrp_size));
736 printf("PART%s%dSTART=%"PRIdaddr"\n", e, part, 736 printf("PART%s%dSTART=%"PRIdaddr"\n", e, part,
737 offset + le32toh(partp->mbrp_start)); 737 offset + le32toh(partp->mbrp_start));
738 printf("PART%s%dFLAG=0x%x\n", e, part, partp->mbrp_flag); 738 printf("PART%s%dFLAG=0x%x\n", e, part, partp->mbrp_flag);
739 printf("PART%s%dBCYL=%d\n", e, part, 739 printf("PART%s%dBCYL=%d\n", e, part,
740 MBR_PCYL(partp->mbrp_scyl, partp->mbrp_ssect)); 740 MBR_PCYL(partp->mbrp_scyl, partp->mbrp_ssect));
741 printf("PART%s%dBHEAD=%d\n", e, part, partp->mbrp_shd); 741 printf("PART%s%dBHEAD=%d\n", e, part, partp->mbrp_shd);
742 printf("PART%s%dBSEC=%d\n", e, part, MBR_PSECT(partp->mbrp_ssect)); 742 printf("PART%s%dBSEC=%d\n", e, part, MBR_PSECT(partp->mbrp_ssect));
743 printf("PART%s%dECYL=%d\n", e, part, 743 printf("PART%s%dECYL=%d\n", e, part,
744 MBR_PCYL(partp->mbrp_ecyl, partp->mbrp_esect)); 744 MBR_PCYL(partp->mbrp_ecyl, partp->mbrp_esect));
745 printf("PART%s%dEHEAD=%d\n", e, part, partp->mbrp_ehd); 745 printf("PART%s%dEHEAD=%d\n", e, part, partp->mbrp_ehd);
746 printf("PART%s%dESEC=%d\n", e, part, MBR_PSECT(partp->mbrp_esect)); 746 printf("PART%s%dESEC=%d\n", e, part, MBR_PSECT(partp->mbrp_esect));
747} 747}
748 748
749static void 749static void
750pr_cyls(daddr_t sector, int is_end) 750pr_cyls(daddr_t sector, int is_end)
751{ 751{
752 unsigned long cyl, head, sect; 752 unsigned long cyl, head, sect;
753 cyl = sector / dos_cylindersectors; 753 cyl = sector / dos_cylindersectors;
754 sect = sector - cyl * dos_cylindersectors; 754 sect = sector - cyl * dos_cylindersectors;
755 head = sect / dos_sectors; 755 head = sect / dos_sectors;
756 sect -= head * dos_sectors; 756 sect -= head * dos_sectors;
757 757
758 printf("%lu", cyl); 758 printf("%lu", cyl);
759 759
760 if (is_end) { 760 if (is_end) {
761 if (head == dos_heads - 1 && sect == dos_sectors - 1) 761 if (head == dos_heads - 1 && sect == dos_sectors - 1)
762 return; 762 return;
763 } else { 763 } else {
764 if (head == 0 && sect == 0) 764 if (head == 0 && sect == 0)
765 return; 765 return;
766 } 766 }
767 767
768 printf("/%lu/%lu", head, sect + 1); 768 printf("/%lu/%lu", head, sect + 1);
769} 769}
770 770
771void 771static void
772print_mbr_partition(struct mbr_sector *boot, int part, 772print_mbr_partition(struct mbr_sector *boot, int part,
773 daddr_t offset, daddr_t exoffset, int indent) 773 daddr_t offset, daddr_t exoffset, int indent)
774{ 774{
775 daddr_t start; 775 daddr_t start;
776 daddr_t size; 776 daddr_t size;
777 struct mbr_partition *partp = &boot->mbr_parts[part]; 777 struct mbr_partition *partp = &boot->mbr_parts[part];
778 struct mbr_sector eboot; 778 struct mbr_sector eboot;
779 int p; 779 int p;
780 static int dumped = 0; 780 static int dumped = 0;
781 781
782 if (partp->mbrp_type == 0 && v_flag < 2) { 782 if (partp->mbrp_type == 0 && v_flag < 2) {
783 printf("<UNUSED>\n"); 783 printf("<UNUSED>\n");
784 return; 784 return;
785 } 785 }
786 786
787 start = le32toh(partp->mbrp_start); 787 start = le32toh(partp->mbrp_start);
788 size = le32toh(partp->mbrp_size); 788 size = le32toh(partp->mbrp_size);
789 if (MBR_IS_EXTENDED(partp->mbrp_type)) 789 if (MBR_IS_EXTENDED(partp->mbrp_type))
790 start += exoffset; 790 start += exoffset;
791 else 791 else
792 start += offset; 792 start += offset;
793 793
794 printf("%s (sysid %d)\n", get_type(partp->mbrp_type), partp->mbrp_type); 794 printf("%s (sysid %d)\n", get_type(partp->mbrp_type), partp->mbrp_type);
795#ifdef BOOTSEL 795#ifdef BOOTSEL
796 if (boot->mbr_bootsel_magic == LE_MBR_BS_MAGIC && 796 if (boot->mbr_bootsel_magic == LE_MBR_BS_MAGIC &&
797 boot->mbr_bootsel.mbrbs_nametab[part][0]) 797 boot->mbr_bootsel.mbrbs_nametab[part][0])
798 printf("%*s bootmenu: %s\n", indent, "", 798 printf("%*s bootmenu: %s\n", indent, "",
799 boot->mbr_bootsel.mbrbs_nametab[part]); 799 boot->mbr_bootsel.mbrbs_nametab[part]);
800#endif 800#endif
801 801
802 printf("%*s start %"PRIdaddr", size %"PRIdaddr, 802 printf("%*s start %"PRIdaddr", size %"PRIdaddr,
803 indent, "", start, size); 803 indent, "", start, size);
804 if (size != 0) { 804 if (size != 0) {
805 printf(" (%u MB, Cyls ", SEC_TO_MB(size)); 805 printf(" (%u MB, Cyls ", SEC_TO_MB(size));
806 if (v_flag == 0 && le32toh(partp->mbrp_start) == ptn_0_offset) 806 if (v_flag == 0 && le32toh(partp->mbrp_start) == ptn_0_offset)
807 pr_cyls(start - ptn_0_offset, 0); 807 pr_cyls(start - ptn_0_offset, 0);
808 else 808 else
809 pr_cyls(start, 0); 809 pr_cyls(start, 0);
810 printf("-"); 810 printf("-");
811 pr_cyls(start + size - 1, 1); 811 pr_cyls(start + size - 1, 1);
812 printf(")"); 812 printf(")");
813 } 813 }
814 814
815 switch (partp->mbrp_flag) { 815 switch (partp->mbrp_flag) {
816 case 0: 816 case 0:
817 break; 817 break;
818 case MBR_PFLAG_ACTIVE: 818 case MBR_PFLAG_ACTIVE:
819 printf(", Active"); 819 printf(", Active");
820 break; 820 break;
821 default: 821 default:
822 printf(", flag 0x%x", partp->mbrp_flag); 822 printf(", flag 0x%x", partp->mbrp_flag);
823 break; 823 break;
824 } 824 }
825 printf("\n"); 825 printf("\n");
826 826
827 if (v_flag) { 827 if (v_flag) {
828 printf("%*s beg: cylinder %4d, head %3d, sector %2d\n", 828 printf("%*s beg: cylinder %4d, head %3d, sector %2d\n",
829 indent, "", 829 indent, "",
830 MBR_PCYL(partp->mbrp_scyl, partp->mbrp_ssect), 830 MBR_PCYL(partp->mbrp_scyl, partp->mbrp_ssect),
831 partp->mbrp_shd, MBR_PSECT(partp->mbrp_ssect)); 831 partp->mbrp_shd, MBR_PSECT(partp->mbrp_ssect));
832 printf("%*s end: cylinder %4d, head %3d, sector %2d\n", 832 printf("%*s end: cylinder %4d, head %3d, sector %2d\n",
833 indent, "", 833 indent, "",
834 MBR_PCYL(partp->mbrp_ecyl, partp->mbrp_esect), 834 MBR_PCYL(partp->mbrp_ecyl, partp->mbrp_esect),
835 partp->mbrp_ehd, MBR_PSECT(partp->mbrp_esect)); 835 partp->mbrp_ehd, MBR_PSECT(partp->mbrp_esect));
836 } 836 }
837 837
838 if (partp->mbrp_type == 0 && start == 0 && v_flag < 3) 838 if (partp->mbrp_type == 0 && start == 0 && v_flag < 3)
839 return; 839 return;
840 840
841 if (! MBR_IS_EXTENDED(partp->mbrp_type)) 841 if (! MBR_IS_EXTENDED(partp->mbrp_type))
842 print_pbr(start, indent + 8, partp->mbrp_type); 842 print_pbr(start, indent + 8, partp->mbrp_type);
843 843
844 if (!MBR_IS_EXTENDED(partp->mbrp_type) || 844 if (!MBR_IS_EXTENDED(partp->mbrp_type) ||
845 (v_flag <= 2 && !ext.is_corrupt)) 845 (v_flag <= 2 && !ext.is_corrupt))
846 return; 846 return;
847 847
848 /* 848 /*
849 * Recursive dump extended table, 849 * Recursive dump extended table,
850 * This is read from the disk - so is wrong during editing. 850 * This is read from the disk - so is wrong during editing.
851 * Just ensure we only show it once. 851 * Just ensure we only show it once.
852 */ 852 */
853 if (dumped) 853 if (dumped)
854 return; 854 return;
855 855
856 printf("%*s Extended partition table:\n", indent, ""); 856 printf("%*s Extended partition table:\n", indent, "");
857 indent += 4; 857 indent += 4;
858 if (read_s0(start, &eboot) == -1) 858 if (read_s0(start, &eboot) == -1)
859 return; 859 return;
860 for (p = 0; p < MBR_PART_COUNT; p++) { 860 for (p = 0; p < MBR_PART_COUNT; p++) {
861 printf("%*s%d: ", indent, "", p); 861 printf("%*s%d: ", indent, "", p);
862 print_mbr_partition(&eboot, p, start, 862 print_mbr_partition(&eboot, p, start,
863 exoffset ? exoffset : start, indent); 863 exoffset ? exoffset : start, indent);
864 } 864 }
865 865
866 if (exoffset == 0) 866 if (exoffset == 0)
867 dumped = 1; 867 dumped = 1;
868} 868}
869 869
870/* Print a line with a label and a vis-encoded string */ 870/* Print a line with a label and a vis-encoded string */
871void 871static void
872printvis(int indent, const char *label, const char *buf, size_t size) 872printvis(int indent, const char *label, const char *buf, size_t size)
873{ 873{
874 char *visbuf; 874 char *visbuf;
875 875
876 if ((visbuf = malloc(size * 4 + 1)) == NULL) 876 if ((visbuf = malloc(size * 4 + 1)) == NULL)
877 err(1, "Malloc failed"); 877 err(1, "Malloc failed");
878 strsvisx(visbuf, buf, size, VIS_TAB|VIS_NL|VIS_OCTAL, "\""); 878 strsvisx(visbuf, buf, size, VIS_TAB|VIS_NL|VIS_OCTAL, "\"");
879 printf("%*s%s: \"%s\"\n", 879 printf("%*s%s: \"%s\"\n",
880 indent, "", 880 indent, "",
881 label, visbuf); 881 label, visbuf);
882 free(visbuf); 882 free(visbuf);
883} 883}
884 884
885/* Check whether a buffer contains all bytes zero */ 885/* Check whether a buffer contains all bytes zero */
886int 886static int
887is_all_zero(const unsigned char *p, size_t size) 887is_all_zero(const unsigned char *p, size_t size)
888{ 888{
889 889
890 while (size-- > 0) { 890 while (size-- > 0) {
891 if (*p++ != 0) 891 if (*p++ != 0)
892 return 0; 892 return 0;
893 } 893 }
894 return 1; 894 return 1;
895} 895}
896 896
897/* 897/*
898 * Report on the contents of a PBR sector. 898 * Report on the contents of a PBR sector.
899 * 899 *
900 * We first perform several sanity checks. If vflag >= 2, we report all 900 * We first perform several sanity checks. If vflag >= 2, we report all
901 * failing tests, but for smaller values of v_flag we stop after the 901 * failing tests, but for smaller values of v_flag we stop after the
902 * first failing test. Tests are ordered in an attempt to get the most 902 * first failing test. Tests are ordered in an attempt to get the most
903 * useful error message from the first failing test. 903 * useful error message from the first failing test.
904 * 904 *
905 * If v_flag >= 2, we also report some decoded values from the PBR. 905 * If v_flag >= 2, we also report some decoded values from the PBR.
906 * These results may be meaningless, if the PBR doesn't follow common 906 * These results may be meaningless, if the PBR doesn't follow common
907 * conventions. 907 * conventions.
908 * 908 *
909 * Trying to decode anything more than the magic number in the last 909 * Trying to decode anything more than the magic number in the last
910 * two bytes is a layering violation, but it can be very useful in 910 * two bytes is a layering violation, but it can be very useful in
911 * diagnosing boot failures. 911 * diagnosing boot failures.
912 */ 912 */
913void 913static void
914print_pbr(daddr_t sector, int indent, uint8_t part_type) 914print_pbr(daddr_t sector, int indent, uint8_t part_type)
915{ 915{
916 struct mbr_sector pboot; 916 struct mbr_sector pboot;
917 unsigned char *p, *endp; 917 unsigned char *p, *endp;
918 unsigned char val; 918 unsigned char val;
919 int ok; 919 int ok;
920 int errcount = 0; 920 int errcount = 0;
921 921
922#define PBR_ERROR(...) \ 922#define PBR_ERROR(...) \
923 do { \ 923 do { \
924 ++errcount; \ 924 ++errcount; \
925 printf("%*s%s: ", indent, "", \ 925 printf("%*s%s: ", indent, "", \
926 (v_flag < 2 ? "PBR is not bootable" : "Not bootable")); \ 926 (v_flag < 2 ? "PBR is not bootable" : "Not bootable")); \
927 printf(__VA_ARGS__); \ 927 printf(__VA_ARGS__); \
928 if (v_flag < 2) \ 928 if (v_flag < 2) \
929 return; \ 929 return; \
930 } while (/*CONSTCOND*/ 0) 930 } while (/*CONSTCOND*/ 0)
931 931
932 if (v_flag >= 2) { 932 if (v_flag >= 2) {
933 printf("%*sInformation from PBR:\n", 933 printf("%*sInformation from PBR:\n",
934 indent, ""); 934 indent, "");
935 indent += 4; 935 indent += 4;
936 } 936 }
937 937
938 if (read_disk(sector, &pboot) == -1) { 938 if (read_disk(sector, &pboot) == -1) {
939 PBR_ERROR("Sector %"PRIdaddr" is unreadable (%s)\n", 939 PBR_ERROR("Sector %"PRIdaddr" is unreadable (%s)\n",
940 sector, strerror(errno)); 940 sector, strerror(errno));
941 return; 941 return;
942 } 942 }
943 943
944 /* all bytes identical? */ 944 /* all bytes identical? */
945 p = (unsigned char *)&pboot; 945 p = (unsigned char *)&pboot;
946 endp = p + sizeof(pboot); 946 endp = p + sizeof(pboot);
947 val = *p; 947 val = *p;
948 ok = 0; 948 ok = 0;
949 for (; p < endp; p++) { 949 for (; p < endp; p++) {
950 if (*p != val) { 950 if (*p != val) {
951 ok = 1; 951 ok = 1;
952 break; 952 break;
953 } 953 }
954 } 954 }
955 if (! ok) 955 if (! ok)
956 PBR_ERROR("All bytes are identical (0x%02x)\n", val); 956 PBR_ERROR("All bytes are identical (0x%02x)\n", val);
957 957
958 if (pboot.mbr_magic != LE_MBR_MAGIC) 958 if (pboot.mbr_magic != LE_MBR_MAGIC)
959 PBR_ERROR("Bad magic number (0x%04x)\n", 959 PBR_ERROR("Bad magic number (0x%04x)\n",
960 le16toh(pboot.mbr_magic)); 960 le16toh(pboot.mbr_magic));
961 961
962#if 0 962#if 0
963 /* Some i386 OS might fail this test. All non-i386 will fail. */ 963 /* Some i386 OS might fail this test. All non-i386 will fail. */
964 if (pboot.mbr_jmpboot[0] != 0xE9 964 if (pboot.mbr_jmpboot[0] != 0xE9
965 && pboot.mbr_jmpboot[0] != 0xEB) { 965 && pboot.mbr_jmpboot[0] != 0xEB) {
966 PBR_ERROR("Does not begin with i386 JMP instruction" 966 PBR_ERROR("Does not begin with i386 JMP instruction"
967 " (0x%02x 0x%02x0 0x%02x)\n", 967 " (0x%02x 0x%02x0 0x%02x)\n",
968 pboot.mbr_jmpboot[0], pboot.mbr_jmpboot[1], 968 pboot.mbr_jmpboot[0], pboot.mbr_jmpboot[1],
969 pboot.mbr_jmpboot[2]); 969 pboot.mbr_jmpboot[2]);
970 } 970 }
971#endif 971#endif
972 972
973 if (v_flag > 0 && errcount == 0) 973 if (v_flag > 0 && errcount == 0)
974 printf("%*sPBR appears to be bootable\n", 974 printf("%*sPBR appears to be bootable\n",
975 indent, ""); 975 indent, "");
976 if (v_flag < 2) 976 if (v_flag < 2)
977 return; 977 return;
978 978
979 if (! is_all_zero(pboot.mbr_oemname, sizeof(pboot.mbr_oemname))) { 979 if (! is_all_zero(pboot.mbr_oemname, sizeof(pboot.mbr_oemname))) {
980 printvis(indent, "OEM name", (char *)pboot.mbr_oemname, 980 printvis(indent, "OEM name", (char *)pboot.mbr_oemname,
981 sizeof(pboot.mbr_oemname)); 981 sizeof(pboot.mbr_oemname));
982 } 982 }
983 983
984 if (pboot.mbr_bpb.bpb16.bsBootSig == 0x29) 984 if (pboot.mbr_bpb.bpb16.bsBootSig == 0x29)
985 printf("%*sBPB FAT16 boot signature found\n", 985 printf("%*sBPB FAT16 boot signature found\n",
986 indent, ""); 986 indent, "");
987 if (pboot.mbr_bpb.bpb32.bsBootSig == 0x29) 987 if (pboot.mbr_bpb.bpb32.bsBootSig == 0x29)
988 printf("%*sBPB FAT32 boot signature found\n", 988 printf("%*sBPB FAT32 boot signature found\n",
989 indent, ""); 989 indent, "");
990 990
991#undef PBR_ERROR 991#undef PBR_ERROR
992} 992}
993 993
994int 994static int
995read_boot(const char *name, void *buf, size_t len, int err_exit) 995read_boot(const char *name, void *buf, size_t len, int err_exit)
996{ 996{
997 int bfd, ret; 997 int bfd, ret;
998 struct stat st; 998 struct stat st;
999 999
1000 if (boot_path != NULL) 1000 if (boot_path != NULL)
1001 free(boot_path); 1001 free(boot_path);
1002 if (strchr(name, '/') == 0) 1002 if (strchr(name, '/') == 0)
1003 asprintf(&boot_path, "%s/%s", boot_dir, name); 1003 asprintf(&boot_path, "%s/%s", boot_dir, name);
1004 else 1004 else
1005 boot_path = strdup(name); 1005 boot_path = strdup(name);
1006 if (boot_path == NULL) 1006 if (boot_path == NULL)
1007 err(1, "Malloc failed"); 1007 err(1, "Malloc failed");
1008 1008
1009 if ((bfd = open(boot_path, O_RDONLY)) < 0 || fstat(bfd, &st) == -1) { 1009 if ((bfd = open(boot_path, O_RDONLY)) < 0 || fstat(bfd, &st) == -1) {
1010 warn("%s", boot_path); 1010 warn("%s", boot_path);
1011 goto fail; 1011 goto fail;
1012 } 1012 }
1013 1013
1014 if (st.st_size > (off_t)len) { 1014 if (st.st_size > (off_t)len) {
1015 warnx("%s: bootcode too large", boot_path); 1015 warnx("%s: bootcode too large", boot_path);
1016 goto fail; 1016 goto fail;
1017 } 1017 }
1018 ret = st.st_size; 1018 ret = st.st_size;
1019 if (ret < 0x200) { 1019 if (ret < 0x200) {
1020 warnx("%s: bootcode too small", boot_path); 1020 warnx("%s: bootcode too small", boot_path);
1021 goto fail; 1021 goto fail;
1022 } 1022 }
1023 if (read(bfd, buf, len) != ret) { 1023 if (read(bfd, buf, len) != ret) {
1024 warn("%s", boot_path); 1024 warn("%s", boot_path);
1025 goto fail; 1025 goto fail;
1026 } 1026 }
1027 1027
1028 /* 1028 /*
1029 * Do some sanity checking here 1029 * Do some sanity checking here
1030 */ 1030 */
1031 if (((struct mbr_sector *)buf)->mbr_magic != LE_MBR_MAGIC) { 1031 if (((struct mbr_sector *)buf)->mbr_magic != LE_MBR_MAGIC) {
1032 warnx("%s: invalid magic", boot_path); 1032 warnx("%s: invalid magic", boot_path);
1033 goto fail; 1033 goto fail;
1034 } 1034 }
1035 1035
1036 close(bfd); 1036 close(bfd);
1037 ret = (ret + 0x1ff) & ~0x1ff; 1037 ret = (ret + 0x1ff) & ~0x1ff;
1038 return ret; 1038 return ret;
1039 1039
1040 fail: 1040 fail:
1041 if (bfd >= 0) 1041 if (bfd >= 0)
1042 close(bfd); 1042 close(bfd);
1043 if (err_exit) 1043 if (err_exit)
1044 exit(1); 1044 exit(1);
1045 return 0; 1045 return 0;
1046} 1046}
1047 1047
1048void 1048static void
1049init_sector0(int zappart) 1049init_sector0(int zappart)
1050{ 1050{
1051 int i; 1051 int i;
1052 int copy_size = offsetof(struct mbr_sector, mbr_dsn); 1052 int copy_size = offsetof(struct mbr_sector, mbr_dsn);
1053 1053
1054#ifdef DEFAULT_BOOTCODE 1054#ifdef DEFAULT_BOOTCODE
1055 if (bootsize == 0) 1055 if (bootsize == 0)
1056 bootsize = read_boot(DEFAULT_BOOTCODE, bootcode, 1056 bootsize = read_boot(DEFAULT_BOOTCODE, bootcode,
1057 sizeof bootcode, 0); 1057 sizeof bootcode, 0);
1058#endif 1058#endif
1059#ifdef BOOTSEL 1059#ifdef BOOTSEL
1060 if (mboot.mbr_bootsel_magic == LE_MBR_BS_MAGIC 1060 if (mboot.mbr_bootsel_magic == LE_MBR_BS_MAGIC
1061 && bootcode[0].mbr_bootsel_magic == LE_MBR_BS_MAGIC) 1061 && bootcode[0].mbr_bootsel_magic == LE_MBR_BS_MAGIC)
1062 copy_size = MBR_BS_OFFSET; 1062 copy_size = MBR_BS_OFFSET;
1063#endif 1063#endif
1064 1064
1065 if (bootsize != 0) { 1065 if (bootsize != 0) {
1066 boot_installed = 1; 1066 boot_installed = 1;
1067 memcpy(&mboot, bootcode, copy_size); 1067 memcpy(&mboot, bootcode, copy_size);
1068 mboot.mbr_bootsel_magic = bootcode[0].mbr_bootsel_magic; 1068 mboot.mbr_bootsel_magic = bootcode[0].mbr_bootsel_magic;
1069 } 1069 }
1070 mboot.mbr_magic = LE_MBR_MAGIC; 1070 mboot.mbr_magic = LE_MBR_MAGIC;
1071  1071
1072 if (!zappart) 1072 if (!zappart)
1073 return; 1073 return;
1074 for (i = 0; i < MBR_PART_COUNT; i++) 1074 for (i = 0; i < MBR_PART_COUNT; i++)
1075 memset(&mboot.mbr_parts[i], 0, sizeof(mboot.mbr_parts[i])); 1075 memset(&mboot.mbr_parts[i], 0, sizeof(mboot.mbr_parts[i]));
1076} 1076}
1077 1077
1078void 1078static void
1079get_extended_ptn(void) 1079get_extended_ptn(void)
1080{ 1080{
1081 struct mbr_partition *mp; 1081 struct mbr_partition *mp;
1082 struct mbr_sector *boot; 1082 struct mbr_sector *boot;
1083 daddr_t offset; 1083 daddr_t offset;
1084 struct mbr_sector *nptn; 1084 struct mbr_sector *nptn;
1085 1085
1086 /* find first (there should only be one) extended partition */ 1086 /* find first (there should only be one) extended partition */
1087 for (mp = mboot.mbr_parts; !MBR_IS_EXTENDED(mp->mbrp_type); mp++) 1087 for (mp = mboot.mbr_parts; !MBR_IS_EXTENDED(mp->mbrp_type); mp++)
1088 if (mp >= &mboot.mbr_parts[MBR_PART_COUNT]) 1088 if (mp >= &mboot.mbr_parts[MBR_PART_COUNT])
1089 return; 1089 return;
1090 1090
1091 /* 1091 /*
1092 * The extended partition should be structured as a linked list 1092 * The extended partition should be structured as a linked list
1093 * (even though it appears, at first glance, to be a tree). 1093 * (even though it appears, at first glance, to be a tree).
1094 */ 1094 */
1095 ext.base = le32toh(mp->mbrp_start); 1095 ext.base = le32toh(mp->mbrp_start);
1096 ext.limit = ext.base + le32toh(mp->mbrp_size); 1096 ext.limit = ext.base + le32toh(mp->mbrp_size);
1097 ext.ptn_id = mp - mboot.mbr_parts; 1097 ext.ptn_id = mp - mboot.mbr_parts;
1098 for (offset = 0;; offset = le32toh(boot->mbr_parts[1].mbrp_start)) { 1098 for (offset = 0;; offset = le32toh(boot->mbr_parts[1].mbrp_start)) {
1099 nptn = realloc(ext.ptn, (ext.num_ptn + 1) * sizeof *ext.ptn); 1099 nptn = realloc(ext.ptn, (ext.num_ptn + 1) * sizeof *ext.ptn);
1100 if (nptn == NULL) 1100 if (nptn == NULL)
1101 err(1, "Malloc failed"); 1101 err(1, "Malloc failed");
1102 ext.ptn = nptn; 1102 ext.ptn = nptn;
1103 boot = ext.ptn + ext.num_ptn; 1103 boot = ext.ptn + ext.num_ptn;
1104 if (read_s0(offset + ext.base, boot) == -1) 1104 if (read_s0(offset + ext.base, boot) == -1)
1105 break; 1105 break;
1106 /* expect p0 to be valid and p1 to be another extended ptn */ 1106 /* expect p0 to be valid and p1 to be another extended ptn */
1107 if (MBR_IS_EXTENDED(boot->mbr_parts[0].mbrp_type)) 1107 if (MBR_IS_EXTENDED(boot->mbr_parts[0].mbrp_type))
1108 break; 1108 break;
1109 if (boot->mbr_parts[1].mbrp_type != 0 && 1109 if (boot->mbr_parts[1].mbrp_type != 0 &&
1110 !MBR_IS_EXTENDED(boot->mbr_parts[1].mbrp_type)) 1110 !MBR_IS_EXTENDED(boot->mbr_parts[1].mbrp_type))
1111 break; 1111 break;
1112 /* p2 and p3 should be unallocated */ 1112 /* p2 and p3 should be unallocated */
1113 if (boot->mbr_parts[2].mbrp_type != 0 || 1113 if (boot->mbr_parts[2].mbrp_type != 0 ||
1114 boot->mbr_parts[3].mbrp_type != 0) 1114 boot->mbr_parts[3].mbrp_type != 0)
1115 break; 1115 break;
1116 /* data ptn inside extended one */ 1116 /* data ptn inside extended one */
1117 if (boot->mbr_parts[0].mbrp_type != 0 && 1117 if (boot->mbr_parts[0].mbrp_type != 0 &&
1118 offset + le32toh(boot->mbr_parts[0].mbrp_start) 1118 offset + le32toh(boot->mbr_parts[0].mbrp_start)
1119 + le32toh(boot->mbr_parts[0].mbrp_size) > ext.limit) 1119 + le32toh(boot->mbr_parts[0].mbrp_size) > ext.limit)
1120 break; 1120 break;
1121 1121
1122 ext.num_ptn++; 1122 ext.num_ptn++;
1123 1123
1124 if (boot->mbr_parts[1].mbrp_type == 0) 1124 if (boot->mbr_parts[1].mbrp_type == 0)
1125 /* end of extended partition chain */ 1125 /* end of extended partition chain */
1126 return; 1126 return;
1127 /* must be in sector order */ 1127 /* must be in sector order */
1128 if (offset >= le32toh(boot->mbr_parts[1].mbrp_start)) 1128 if (offset >= le32toh(boot->mbr_parts[1].mbrp_start))
1129 break; 1129 break;
1130 } 1130 }
1131 1131
1132 warnx("Extended partition table is corrupt\n"); 1132 warnx("Extended partition table is corrupt\n");
1133 ext.is_corrupt = 1; 1133 ext.is_corrupt = 1;
1134 ext.num_ptn = 0; 1134 ext.num_ptn = 0;
1135} 1135}
1136 1136
1137#if defined(USE_DISKLIST) 1137#if defined(USE_DISKLIST)
1138void  1138static void
1139get_diskname(const char *fullname, char *diskname, size_t size) 1139get_diskname(const char *fullname, char *diskname, size_t size)
1140{  1140{
1141 const char *p, *p2; 1141 const char *p, *p2;
1142 size_t len; 1142 size_t len;
1143 1143
1144 p = strrchr(fullname, '/'); 1144 p = strrchr(fullname, '/');
1145 if (p == NULL) 1145 if (p == NULL)
1146 p = fullname; 1146 p = fullname;
1147 else 1147 else
1148 p++; 1148 p++;
1149 1149
1150 if (*p == 0) { 1150 if (*p == 0) {
1151 strlcpy(diskname, fullname, size); 1151 strlcpy(diskname, fullname, size);
1152 return; 1152 return;
1153 } 1153 }
1154 1154
1155 if (*p == 'r') 1155 if (*p == 'r')
1156 p++; 1156 p++;
1157 1157
1158 for (p2 = p; *p2 != 0; p2++) 1158 for (p2 = p; *p2 != 0; p2++)
1159 if (isdigit((unsigned char)*p2)) 1159 if (isdigit((unsigned char)*p2))
1160 break; 1160 break;
1161 if (*p2 == 0) { 1161 if (*p2 == 0) {
1162 /* XXX invalid diskname? */ 1162 /* XXX invalid diskname? */
1163 strlcpy(diskname, fullname, size); 1163 strlcpy(diskname, fullname, size);
1164 return; 1164 return;
1165 } 1165 }
1166 while (isdigit((unsigned char)*p2)) 1166 while (isdigit((unsigned char)*p2))
1167 p2++;  1167 p2++;
1168 1168
1169 len = p2 - p; 1169 len = p2 - p;
1170 if (len > size) { 1170 if (len > size) {
1171 /* XXX */ 1171 /* XXX */
1172 strlcpy(diskname, fullname, size); 1172 strlcpy(diskname, fullname, size);
1173 return; 1173 return;
1174 } 1174 }
1175  1175
1176 memcpy(diskname, p, len); 1176 memcpy(diskname, p, len);
1177 diskname[len] = 0; 1177 diskname[len] = 0;
1178} 1178}
1179#endif 1179#endif
1180 1180
1181static void 1181static void
1182get_ptn_alignmemt(void) 1182get_ptn_alignmemt(void)
1183{ 1183{
1184 struct mbr_partition *partp = &mboot.mbr_parts[0]; 1184 struct mbr_partition *partp = &mboot.mbr_parts[0];
1185 uint32_t ptn_0_base, ptn_0_limit; 1185 uint32_t ptn_0_base, ptn_0_limit;
1186 1186
1187 /* Default to using 'traditional' cylinder alignment */ 1187 /* Default to using 'traditional' cylinder alignment */
1188 ptn_alignment = dos_cylindersectors; 1188 ptn_alignment = dos_cylindersectors;
1189 ptn_0_offset = dos_sectors; 1189 ptn_0_offset = dos_sectors;
1190 1190
1191 if (partp->mbrp_type != 0) { 1191 if (partp->mbrp_type != 0) {
1192 /* Try to copy alignment of first partition */ 1192 /* Try to copy alignment of first partition */
1193 ptn_0_base = le32toh(partp->mbrp_start); 1193 ptn_0_base = le32toh(partp->mbrp_start);
1194 ptn_0_limit = ptn_0_base + le32toh(partp->mbrp_size); 1194 ptn_0_limit = ptn_0_base + le32toh(partp->mbrp_size);
1195 if (!(ptn_0_limit & 2047)) { 1195 if (!(ptn_0_limit & 2047)) {
1196 /* Partition ends on a 1MB boundary, align to 1MB */ 1196 /* Partition ends on a 1MB boundary, align to 1MB */
1197 ptn_alignment = 2048; 1197 ptn_alignment = 2048;
1198 if (ptn_0_base <= 2048 1198 if (ptn_0_base <= 2048
1199 && !(ptn_0_base & (ptn_0_base - 1))) { 1199 && !(ptn_0_base & (ptn_0_base - 1))) {
1200 /* ptn_base is a power of 2, use it */ 1200 /* ptn_base is a power of 2, use it */
1201 ptn_0_offset = ptn_0_base; 1201 ptn_0_offset = ptn_0_base;
1202 } 1202 }
1203 } 1203 }
1204 } else { 1204 } else {
1205 /* Use 1MB alignment for large disks */ 1205 /* Use 1MB alignment for large disks */
1206 if (disksectors > 2048 * 1024 * 128) { 1206 if (disksectors > 2048 * 1024 * 128) {
1207 ptn_alignment = 2048; 1207 ptn_alignment = 2048;
1208 ptn_0_offset = 2048; 1208 ptn_0_offset = 2048;
1209 } 1209 }
1210 } 1210 }
1211} 1211}
1212 1212
1213void 1213static void
1214get_bios_geometry(void) 1214get_bios_geometry(void)
1215{ 1215{
1216#if defined(USE_DISKLIST) 1216#if defined(USE_DISKLIST)
1217 int mib[2], i; 1217 int mib[2], i;
1218 size_t len; 1218 size_t len;
1219 struct biosdisk_info *bip; 1219 struct biosdisk_info *bip;
1220 struct nativedisk_info *nip; 1220 struct nativedisk_info *nip;
1221 char diskname[8]; 1221 char diskname[8];
1222 1222
1223 mib[0] = CTL_MACHDEP; 1223 mib[0] = CTL_MACHDEP;
1224 mib[1] = CPU_DISKINFO; 1224 mib[1] = CPU_DISKINFO;
1225 if (sysctl(mib, 2, NULL, &len, NULL, 0) < 0) { 1225 if (sysctl(mib, 2, NULL, &len, NULL, 0) < 0) {
1226 goto out; 1226 goto out;
1227 } 1227 }
1228 dl = (struct disklist *) malloc(len); 1228 dl = (struct disklist *) malloc(len);
1229 if (dl == NULL) 1229 if (dl == NULL)
1230 err(1, "Malloc failed"); 1230 err(1, "Malloc failed");
1231 if (sysctl(mib, 2, dl, &len, NULL, 0) < 0) { 1231 if (sysctl(mib, 2, dl, &len, NULL, 0) < 0) {
1232 free(dl); 1232 free(dl);
1233 dl = 0; 1233 dl = 0;
1234 goto out; 1234 goto out;
1235 } 1235 }
1236 1236
1237 get_diskname(disk, diskname, sizeof diskname); 1237 get_diskname(disk, diskname, sizeof diskname);
1238 1238
1239 for (i = 0; i < dl->dl_nnativedisks; i++) { 1239 for (i = 0; i < dl->dl_nnativedisks; i++) {
1240 nip = &dl->dl_nativedisks[i]; 1240 nip = &dl->dl_nativedisks[i];
1241 if (strcmp(diskname, nip->ni_devname)) 1241 if (strcmp(diskname, nip->ni_devname))
1242 continue; 1242 continue;
1243 /* 1243 /*
1244 * XXX listing possible matches is better. This is ok for 1244 * XXX listing possible matches is better. This is ok for
1245 * now because the user has a chance to change it later. 1245 * now because the user has a chance to change it later.
1246 * Also, if all the disks have the same parameters then we can 1246 * Also, if all the disks have the same parameters then we can
1247 * just use them, we don't need to know which disk is which. 1247 * just use them, we don't need to know which disk is which.
1248 */ 1248 */
1249 if (nip->ni_nmatches != 0) { 1249 if (nip->ni_nmatches != 0) {
1250 bip = &dl->dl_biosdisks[nip->ni_biosmatches[0]]; 1250 bip = &dl->dl_biosdisks[nip->ni_biosmatches[0]];
1251 dos_cylinders = bip->bi_cyl; 1251 dos_cylinders = bip->bi_cyl;
1252 dos_heads = bip->bi_head; 1252 dos_heads = bip->bi_head;
1253 dos_sectors = bip->bi_sec; 1253 dos_sectors = bip->bi_sec;
1254 if (bip->bi_lbasecs) 1254 if (bip->bi_lbasecs)
1255 dos_disksectors = bip->bi_lbasecs; 1255 dos_disksectors = bip->bi_lbasecs;
1256 return; 1256 return;
1257 } 1257 }
1258 } 1258 }
1259 out: 1259 out:
1260#endif 1260#endif
1261 /* Allright, allright, make a stupid guess.. */ 1261 /* Allright, allright, make a stupid guess.. */
1262 intuit_translated_geometry(); 1262 intuit_translated_geometry();
1263} 1263}
1264 1264
1265#ifdef BOOTSEL 1265#ifdef BOOTSEL
1266daddr_t 1266static daddr_t
1267get_default_boot(void) 1267get_default_boot(void)
1268{ 1268{
1269 unsigned int id; 1269 unsigned int id;
1270 int p; 1270 int p;
1271 1271
1272 if (mboot.mbr_bootsel_magic != LE_MBR_BS_MAGIC) 1272 if (mboot.mbr_bootsel_magic != LE_MBR_BS_MAGIC)
1273 /* default to first active partition */ 1273 /* default to first active partition */
1274 return DEFAULT_ACTIVE; 1274 return DEFAULT_ACTIVE;
1275 1275
1276 id = mboot.mbr_bootsel.mbrbs_defkey; 1276 id = mboot.mbr_bootsel.mbrbs_defkey;
1277 1277
1278 if (mboot.mbr_bootsel.mbrbs_flags & MBR_BS_ASCII) { 1278 if (mboot.mbr_bootsel.mbrbs_flags & MBR_BS_ASCII) {
1279 /* Keycode is ascii */ 1279 /* Keycode is ascii */
1280 if (id == '\r') 1280 if (id == '\r')
1281 return DEFAULT_ACTIVE; 1281 return DEFAULT_ACTIVE;
1282 /* '1'+ => allocated partition id, 'a'+ => disk 0+ */ 1282 /* '1'+ => allocated partition id, 'a'+ => disk 0+ */
1283 if (id >= 'a' && id < 'a' + MAX_BIOS_DISKS) 1283 if (id >= 'a' && id < 'a' + MAX_BIOS_DISKS)
1284 return DEFAULT_DISK(id - 'a'); 1284 return DEFAULT_DISK(id - 'a');
1285 id -= '1'; 1285 id -= '1';
1286 } else { 1286 } else {
1287 /* keycode is PS/2 keycode */ 1287 /* keycode is PS/2 keycode */
1288 if (id == SCAN_ENTER) 1288 if (id == SCAN_ENTER)
1289 return DEFAULT_ACTIVE; 1289 return DEFAULT_ACTIVE;
1290 /* 1+ => allocated partition id, F1+ => disk 0+ */ 1290 /* 1+ => allocated partition id, F1+ => disk 0+ */
1291 if (id >= SCAN_F1 && id < SCAN_F1 + MAX_BIOS_DISKS) 1291 if (id >= SCAN_F1 && id < SCAN_F1 + MAX_BIOS_DISKS)
1292 return DEFAULT_DISK(id - SCAN_F1); 1292 return DEFAULT_DISK(id - SCAN_F1);
1293 id -= SCAN_1; 1293 id -= SCAN_1;
1294 } 1294 }
1295 1295
1296 /* Convert partition index to the invariant start sector number */ 1296 /* Convert partition index to the invariant start sector number */
1297 1297
1298 for (p = 0; p < MBR_PART_COUNT; p++) { 1298 for (p = 0; p < MBR_PART_COUNT; p++) {
1299 if (mboot.mbr_parts[p].mbrp_type == 0) 1299 if (mboot.mbr_parts[p].mbrp_type == 0)
1300 continue; 1300 continue;
1301 if (mboot.mbr_bootsel.mbrbs_nametab[p][0] == 0) 1301 if (mboot.mbr_bootsel.mbrbs_nametab[p][0] == 0)
1302 continue; 1302 continue;
1303 if (id-- == 0) 1303 if (id-- == 0)
1304 return le32toh(mboot.mbr_parts[p].mbrp_start); 1304 return le32toh(mboot.mbr_parts[p].mbrp_start);
1305 } 1305 }
1306 1306
1307 for (p = 0; p < ext.num_ptn; p++) { 1307 for (p = 0; p < ext.num_ptn; p++) {
1308 if (ext.ptn[p].mbr_parts[0].mbrp_type == 0) 1308 if (ext.ptn[p].mbr_parts[0].mbrp_type == 0)
1309 continue; 1309 continue;
1310 if (ext.ptn[p].mbr_bootsel.mbrbs_nametab[0][0] == 0) 1310 if (ext.ptn[p].mbr_bootsel.mbrbs_nametab[0][0] == 0)
1311 continue; 1311 continue;
1312 if (id-- == 0) 1312 if (id-- == 0)
1313 return ext_offset(p) 1313 return ext_offset(p)
1314 + le32toh(ext.ptn[p].mbr_parts[0].mbrp_start); 1314 + le32toh(ext.ptn[p].mbr_parts[0].mbrp_start);
1315 } 1315 }
1316 1316
1317 return DEFAULT_ACTIVE; 1317 return DEFAULT_ACTIVE;
1318} 1318}
1319 1319
1320void 1320static void
1321set_default_boot(daddr_t default_ptn) 1321set_default_boot(daddr_t default_ptn)
1322{ 1322{
1323 int p; 1323 int p;
1324 static const unsigned char key_list[] = { SCAN_ENTER, SCAN_F1, SCAN_1, 1324 static const unsigned char key_list[] = { SCAN_ENTER, SCAN_F1, SCAN_1,
1325 '\r', 'a', '1' }; 1325 '\r', 'a', '1' };
1326 const unsigned char *key = key_list; 1326 const unsigned char *key = key_list;
1327 1327
1328 if (mboot.mbr_bootsel_magic != LE_MBR_BS_MAGIC) 1328 if (mboot.mbr_bootsel_magic != LE_MBR_BS_MAGIC)
1329 /* sanity */ 1329 /* sanity */
1330 return; 1330 return;
1331 1331
1332 if (mboot.mbr_bootsel.mbrbs_flags & MBR_BS_ASCII) 1332 if (mboot.mbr_bootsel.mbrbs_flags & MBR_BS_ASCII)
1333 /* Use ascii values */ 1333 /* Use ascii values */
1334 key += 3; 1334 key += 3;
1335 1335
1336 if (default_ptn == DEFAULT_ACTIVE) { 1336 if (default_ptn == DEFAULT_ACTIVE) {
1337 mboot.mbr_bootsel.mbrbs_defkey = key[0]; 1337 mboot.mbr_bootsel.mbrbs_defkey = key[0];
1338 return; 1338 return;
1339 } 1339 }
1340 1340
1341 if (default_ptn >= DEFAULT_DISK(0) 1341 if (default_ptn >= DEFAULT_DISK(0)
1342 && default_ptn < DEFAULT_DISK(MAX_BIOS_DISKS)) { 1342 && default_ptn < DEFAULT_DISK(MAX_BIOS_DISKS)) {
1343 mboot.mbr_bootsel.mbrbs_defkey = key[1] 1343 mboot.mbr_bootsel.mbrbs_defkey = key[1]
1344 + default_ptn - DEFAULT_DISK(0); 1344 + default_ptn - DEFAULT_DISK(0);
1345 return; 1345 return;
1346 } 1346 }
1347 1347
1348 mboot.mbr_bootsel.mbrbs_defkey = key[2]; 1348 mboot.mbr_bootsel.mbrbs_defkey = key[2];
1349 for (p = 0; p < MBR_PART_COUNT; p++) { 1349 for (p = 0; p < MBR_PART_COUNT; p++) {
1350 if (mboot.mbr_parts[p].mbrp_type == 0) 1350 if (mboot.mbr_parts[p].mbrp_type == 0)
1351 continue; 1351 continue;
1352 if (mboot.mbr_bootsel.mbrbs_nametab[p][0] == 0) 1352 if (mboot.mbr_bootsel.mbrbs_nametab[p][0] == 0)
1353 continue; 1353 continue;
1354 if (le32toh(mboot.mbr_parts[p].mbrp_start) == default_ptn) 1354 if (le32toh(mboot.mbr_parts[p].mbrp_start) == default_ptn)
1355 return; 1355 return;
1356 mboot.mbr_bootsel.mbrbs_defkey++; 1356 mboot.mbr_bootsel.mbrbs_defkey++;
1357 } 1357 }
1358 1358
1359 if (mboot.mbr_bootsel.mbrbs_flags & MBR_BS_EXTLBA) { 1359 if (mboot.mbr_bootsel.mbrbs_flags & MBR_BS_EXTLBA) {
1360 for (p = 0; p < ext.num_ptn; p++) { 1360 for (p = 0; p < ext.num_ptn; p++) {
1361 if (ext.ptn[p].mbr_parts[0].mbrp_type == 0) 1361 if (ext.ptn[p].mbr_parts[0].mbrp_type == 0)
1362 continue; 1362 continue;
1363 if (ext.ptn[p].mbr_bootsel.mbrbs_nametab[0][0] == 0) 1363 if (ext.ptn[p].mbr_bootsel.mbrbs_nametab[0][0] == 0)
1364 continue; 1364 continue;
1365 if (le32toh(ext.ptn[p].mbr_parts[0].mbrp_start) + 1365 if (le32toh(ext.ptn[p].mbr_parts[0].mbrp_start) +
1366 ext_offset(p) == default_ptn) 1366 ext_offset(p) == default_ptn)
1367 return; 1367 return;
1368 mboot.mbr_bootsel.mbrbs_defkey++; 1368 mboot.mbr_bootsel.mbrbs_defkey++;
1369 } 1369 }
1370 } 1370 }
1371 1371
1372 /* Default to first active partition */ 1372 /* Default to first active partition */
1373 mboot.mbr_bootsel.mbrbs_defkey = key[0]; 1373 mboot.mbr_bootsel.mbrbs_defkey = key[0];
1374} 1374}
1375 1375
1376void 1376static void
1377install_bootsel(int needed) 1377install_bootsel(int needed)
1378{ 1378{
1379 struct mbr_bootsel *mbs = &mboot.mbr_bootsel; 1379 struct mbr_bootsel *mbs = &mboot.mbr_bootsel;
1380 int p; 1380 int p;
1381 int ext13 = 0; 1381 int ext13 = 0;
1382 const char *code; 1382 const char *code;
1383 1383
1384 needed |= MBR_BS_NEWMBR; /* need new bootsel code */ 1384 needed |= MBR_BS_NEWMBR; /* need new bootsel code */
1385 1385
1386 /* Work out which boot code we need for this configuration */ 1386 /* Work out which boot code we need for this configuration */
1387 for (p = 0; p < MBR_PART_COUNT; p++) { 1387 for (p = 0; p < MBR_PART_COUNT; p++) {
1388 if (mboot.mbr_parts[p].mbrp_type == 0) 1388 if (mboot.mbr_parts[p].mbrp_type == 0)
1389 continue; 1389 continue;
1390 if (mboot.mbr_bootsel_magic != LE_MBR_BS_MAGIC) 1390 if (mboot.mbr_bootsel_magic != LE_MBR_BS_MAGIC)
1391 break; 1391 break;
1392 if (mbs->mbrbs_nametab[p][0] == 0) 1392 if (mbs->mbrbs_nametab[p][0] == 0)
1393 continue; 1393 continue;
1394 needed |= MBR_BS_ACTIVE; 1394 needed |= MBR_BS_ACTIVE;
1395 if (le32toh(mboot.mbr_parts[p].mbrp_start) >= dos_totalsectors) 1395 if (le32toh(mboot.mbr_parts[p].mbrp_start) >= dos_totalsectors)
1396 ext13 = MBR_BS_EXTINT13; 1396 ext13 = MBR_BS_EXTINT13;
1397 } 1397 }
1398 1398
1399 for (p = 0; p < ext.num_ptn; p++) { 1399 for (p = 0; p < ext.num_ptn; p++) {
1400 if (ext.ptn[p].mbr_bootsel_magic != LE_MBR_BS_MAGIC) 1400 if (ext.ptn[p].mbr_bootsel_magic != LE_MBR_BS_MAGIC)
1401 continue; 1401 continue;
1402 if (ext.ptn[p].mbr_parts[0].mbrp_type == 0) 1402 if (ext.ptn[p].mbr_parts[0].mbrp_type == 0)
1403 continue; 1403 continue;
1404 if (ext.ptn[p].mbr_bootsel.mbrbs_nametab[p][0] == 0) 1404 if (ext.ptn[p].mbr_bootsel.mbrbs_nametab[p][0] == 0)
1405 continue; 1405 continue;
1406 needed |= MBR_BS_EXTLBA | MBR_BS_ACTIVE; 1406 needed |= MBR_BS_EXTLBA | MBR_BS_ACTIVE;
1407 } 1407 }
1408 1408
1409 if (B_flag) 1409 if (B_flag)
1410 needed |= MBR_BS_ACTIVE; 1410 needed |= MBR_BS_ACTIVE;
1411 1411
1412 /* Is the installed code good enough ? */ 1412 /* Is the installed code good enough ? */
1413 if (!i_flag && (needed == 0 || 1413 if (!i_flag && (needed == 0 ||
1414 (mboot.mbr_bootsel_magic == LE_MBR_BS_MAGIC 1414 (mboot.mbr_bootsel_magic == LE_MBR_BS_MAGIC
1415 && (mbs->mbrbs_flags & needed) == needed))) { 1415 && (mbs->mbrbs_flags & needed) == needed))) {
1416 /* yes - just set flags */ 1416 /* yes - just set flags */
1417 mbs->mbrbs_flags |= ext13; 1417 mbs->mbrbs_flags |= ext13;
1418 return; 1418 return;
1419 } 1419 }
1420 1420
1421 /* ok - we need to replace the bootcode */ 1421 /* ok - we need to replace the bootcode */
1422 1422
1423 if (f_flag && !(i_flag || B_flag)) { 1423 if (f_flag && !(i_flag || B_flag)) {
1424 warnx("Installed bootfile doesn't support required options."); 1424 warnx("Installed bootfile doesn't support required options.");
1425 return; 1425 return;
1426 } 1426 }
1427 1427
1428 if (!f_flag && bootsize == 0 && !i_flag) 1428 if (!f_flag && bootsize == 0 && !i_flag)
1429 /* Output an explanation for the 'update bootcode' prompt. */ 1429 /* Output an explanation for the 'update bootcode' prompt. */
1430 printf("\n%s\n", 1430 printf("\n%s\n",
1431 "Installed bootfile doesn't support required options."); 1431 "Installed bootfile doesn't support required options.");
1432 1432
1433 /* Were we told a specific file ? (which we have already read) */ 1433 /* Were we told a specific file ? (which we have already read) */
1434 /* If so check that it supports what we need. */ 1434 /* If so check that it supports what we need. */
1435 if (bootsize != 0 && needed != 0 1435 if (bootsize != 0 && needed != 0
1436 && (bootcode[0].mbr_bootsel_magic != LE_MBR_BS_MAGIC 1436 && (bootcode[0].mbr_bootsel_magic != LE_MBR_BS_MAGIC
1437 || ((bootcode[0].mbr_bootsel.mbrbs_flags & needed) != needed))) { 1437 || ((bootcode[0].mbr_bootsel.mbrbs_flags & needed) != needed))) {
1438 /* No it doesn't... */ 1438 /* No it doesn't... */
1439 if (f_flag) 1439 if (f_flag)
1440 warnx("Bootfile %s doesn't support " 1440 warnx("Bootfile %s doesn't support "
1441 "required bootsel options", boot_path ); 1441 "required bootsel options", boot_path );
1442 /* But install it anyway */ 1442 /* But install it anyway */
1443 else 1443 else
1444 if (yesno("Bootfile %s doesn't support the required " 1444 if (yesno("Bootfile %s doesn't support the required "
1445 "options,\ninstall default bootfile instead?", 1445 "options,\ninstall default bootfile instead?",
1446 boot_path)) 1446 boot_path))
1447 bootsize = 0; 1447 bootsize = 0;
1448 } 1448 }
1449 1449
1450 if (bootsize == 0) { 1450 if (bootsize == 0) {
1451 /* Get name of bootfile that supports the required facilities */ 1451 /* Get name of bootfile that supports the required facilities */
1452 code = DEFAULT_BOOTCODE; 1452 code = DEFAULT_BOOTCODE;
1453 if (needed & MBR_BS_ACTIVE) 1453 if (needed & MBR_BS_ACTIVE)
1454 code = DEFAULT_BOOTSELCODE; 1454 code = DEFAULT_BOOTSELCODE;
1455#ifdef DEFAULT_BOOTEXTCODE 1455#ifdef DEFAULT_BOOTEXTCODE
1456 if (needed & MBR_BS_EXTLBA) 1456 if (needed & MBR_BS_EXTLBA)
1457 code = DEFAULT_BOOTEXTCODE; 1457 code = DEFAULT_BOOTEXTCODE;
1458#endif 1458#endif
1459 1459
1460 bootsize = read_boot(code, bootcode, sizeof bootcode, 0); 1460 bootsize = read_boot(code, bootcode, sizeof bootcode, 0);
1461 if (bootsize == 0) 1461 if (bootsize == 0)
1462 /* The old bootcode is better than no bootcode at all */ 1462 /* The old bootcode is better than no bootcode at all */
1463 return; 1463 return;
1464 if ((bootcode[0].mbr_bootsel.mbrbs_flags & needed) != needed) 1464 if ((bootcode[0].mbr_bootsel.mbrbs_flags & needed) != needed)
1465 warnx("Default bootfile %s doesn't support required " 1465 warnx("Default bootfile %s doesn't support required "
1466 "options. Got flags 0x%x, wanted 0x%x\n", 1466 "options. Got flags 0x%x, wanted 0x%x\n",
1467 boot_path, bootcode[0].mbr_bootsel.mbrbs_flags, 1467 boot_path, bootcode[0].mbr_bootsel.mbrbs_flags,
1468 needed); 1468 needed);
1469 } 1469 }
1470 1470
1471 if (!f_flag && !yesno("Update the bootcode from %s?", boot_path)) 1471 if (!f_flag && !yesno("Update the bootcode from %s?", boot_path))
1472 return; 1472 return;
1473 1473
1474 init_sector0(0); 1474 init_sector0(0);
1475 1475
1476 if (mboot.mbr_bootsel_magic == LE_MBR_BS_MAGIC) 1476 if (mboot.mbr_bootsel_magic == LE_MBR_BS_MAGIC)
1477 mbs->mbrbs_flags = bootcode[0].mbr_bootsel.mbrbs_flags | ext13; 1477 mbs->mbrbs_flags = bootcode[0].mbr_bootsel.mbrbs_flags | ext13;
1478} 1478}
1479 1479
1480daddr_t 1480static daddr_t
1481configure_bootsel(daddr_t default_ptn) 1481configure_bootsel(daddr_t default_ptn)
1482{ 1482{
1483 struct mbr_bootsel *mbs = &mboot.mbr_bootsel; 1483 struct mbr_bootsel *mbs = &mboot.mbr_bootsel;
1484 int i, item, opt; 1484 int i, item, opt;
1485 int tmo; 1485 int tmo;
1486 daddr_t *off; 1486 daddr_t *off;
1487 int num_bios_disks; 1487 int num_bios_disks;
1488 1488
1489#if defined(USE_DISKLIST) 1489#if defined(USE_DISKLIST)
1490 if (dl != NULL) { 1490 if (dl != NULL) {
1491 num_bios_disks = dl->dl_nbiosdisks; 1491 num_bios_disks = dl->dl_nbiosdisks;
1492 if (num_bios_disks > MAX_BIOS_DISKS) 1492 if (num_bios_disks > MAX_BIOS_DISKS)
1493 num_bios_disks = MAX_BIOS_DISKS; 1493 num_bios_disks = MAX_BIOS_DISKS;
1494 } else 1494 } else
1495#endif 1495#endif
1496 num_bios_disks = MAX_BIOS_DISKS; 1496 num_bios_disks = MAX_BIOS_DISKS;
1497 1497
1498 printf("\nBoot selector configuration:\n"); 1498 printf("\nBoot selector configuration:\n");
1499 1499
1500 /* The timeout value is in ticks, ~18.2 Hz. Avoid using floats. 1500 /* The timeout value is in ticks, ~18.2 Hz. Avoid using floats.
1501 * Ticks are nearly 64k/3600 - so our long timers are sligtly out! 1501 * Ticks are nearly 64k/3600 - so our long timers are sligtly out!
1502 * Newer bootcode always waits for 1 tick, so treats 0xffff 1502 * Newer bootcode always waits for 1 tick, so treats 0xffff
1503 * as wait forever. 1503 * as wait forever.
1504 */ 1504 */
1505 tmo = le16toh(mbs->mbrbs_timeo); 1505 tmo = le16toh(mbs->mbrbs_timeo);
1506 tmo = tmo == 0xffff ? -1 : (10 * tmo + 9) / 182; 1506 tmo = tmo == 0xffff ? -1 : (10 * tmo + 9) / 182;
1507 tmo = decimal("Timeout value (0 to 3600 seconds, -1 => never)", 1507 tmo = decimal("Timeout value (0 to 3600 seconds, -1 => never)",
1508 tmo, 0, -1, 3600); 1508 tmo, 0, -1, 3600);
1509 mbs->mbrbs_timeo = htole16(tmo == -1 ? 0xffff : (tmo * 182) / 10); 1509 mbs->mbrbs_timeo = htole16(tmo == -1 ? 0xffff : (tmo * 182) / 10);
1510 1510
1511 off = calloc(1 + MBR_PART_COUNT + ext.num_ptn + num_bios_disks, sizeof *off); 1511 off = calloc(1 + MBR_PART_COUNT + ext.num_ptn + num_bios_disks, sizeof *off);
1512 if (off == NULL) 1512 if (off == NULL)
1513 err(1, "Malloc failed"); 1513 err(1, "Malloc failed");
1514 1514
1515 printf("Select the default boot option. Options are:\n\n"); 1515 printf("Select the default boot option. Options are:\n\n");
1516 item = 0; 1516 item = 0;
1517 opt = 0; 1517 opt = 0;
1518 off[opt] = DEFAULT_ACTIVE; 1518 off[opt] = DEFAULT_ACTIVE;
1519 printf("%d: The first active partition\n", opt); 1519 printf("%d: The first active partition\n", opt);
1520 for (i = 0; i < MBR_PART_COUNT; i++) { 1520 for (i = 0; i < MBR_PART_COUNT; i++) {
1521 if (mboot.mbr_parts[i].mbrp_type == 0) 1521 if (mboot.mbr_parts[i].mbrp_type == 0)
1522 continue; 1522 continue;
1523 if (mbs->mbrbs_nametab[i][0] == 0) 1523 if (mbs->mbrbs_nametab[i][0] == 0)
1524 continue; 1524 continue;
1525 printf("%d: %s\n", ++opt, &mbs->mbrbs_nametab[i][0]); 1525 printf("%d: %s\n", ++opt, &mbs->mbrbs_nametab[i][0]);
1526 off[opt] = le32toh(mboot.mbr_parts[i].mbrp_start); 1526 off[opt] = le32toh(mboot.mbr_parts[i].mbrp_start);
1527 if (off[opt] == default_ptn) 1527 if (off[opt] == default_ptn)
1528 item = opt; 1528 item = opt;
1529 } 1529 }
1530 if (mbs->mbrbs_flags & MBR_BS_EXTLBA) { 1530 if (mbs->mbrbs_flags & MBR_BS_EXTLBA) {
1531 for (i = 0; i < ext.num_ptn; i++) { 1531 for (i = 0; i < ext.num_ptn; i++) {
1532 if (ext.ptn[i].mbr_parts[0].mbrp_type == 0) 1532 if (ext.ptn[i].mbr_parts[0].mbrp_type == 0)
1533 continue; 1533 continue;
1534 if (ext.ptn[i].mbr_bootsel.mbrbs_nametab[0][0] == 0) 1534 if (ext.ptn[i].mbr_bootsel.mbrbs_nametab[0][0] == 0)
1535 continue; 1535 continue;
1536 printf("%d: %s\n", 1536 printf("%d: %s\n",
1537 ++opt, ext.ptn[i].mbr_bootsel.mbrbs_nametab[0]); 1537 ++opt, ext.ptn[i].mbr_bootsel.mbrbs_nametab[0]);
1538 off[opt] = ext_offset(i) + 1538 off[opt] = ext_offset(i) +
1539 le32toh(ext.ptn[i].mbr_parts[0].mbrp_start); 1539 le32toh(ext.ptn[i].mbr_parts[0].mbrp_start);
1540 if (off[opt] == default_ptn) 1540 if (off[opt] == default_ptn)
1541 item = opt; 1541 item = opt;
1542 } 1542 }
1543 } 1543 }
1544 for (i = 0; i < num_bios_disks; i++) { 1544 for (i = 0; i < num_bios_disks; i++) {
1545 printf("%d: Harddisk %d\n", ++opt, i); 1545 printf("%d: Harddisk %d\n", ++opt, i);
1546 off[opt] = DEFAULT_DISK(i); 1546 off[opt] = DEFAULT_DISK(i);
1547 if (DEFAULT_DISK(i) == default_ptn) 1547 if (DEFAULT_DISK(i) == default_ptn)
1548 item = opt; 1548 item = opt;
1549 } 1549 }
1550 1550
1551 item = decimal("Default boot option", item, 0, 0, opt); 1551 item = decimal("Default boot option", item, 0, 0, opt);
1552 1552
1553 default_ptn = off[item]; 1553 default_ptn = off[item];
1554 free(off); 1554 free(off);
1555 return default_ptn; 1555 return default_ptn;
1556} 1556}
1557#endif /* BOOTSEL */ 1557#endif /* BOOTSEL */
1558 1558
1559 1559
1560/* Prerequisite: the disklabel parameters and master boot record must 1560/* Prerequisite: the disklabel parameters and master boot record must
1561 * have been read (i.e. dos_* and mboot are meaningful). 1561 * have been read (i.e. dos_* and mboot are meaningful).
1562 * Specification: modifies dos_cylinders, dos_heads, dos_sectors, and 1562 * Specification: modifies dos_cylinders, dos_heads, dos_sectors, and
1563 * dos_cylindersectors to be consistent with what the 1563 * dos_cylindersectors to be consistent with what the
1564 * partition table is using, if we can find a geometry 1564 * partition table is using, if we can find a geometry
1565 * which is consistent with all partition table entries. 1565 * which is consistent with all partition table entries.
1566 * We may get the number of cylinders slightly wrong (in 1566 * We may get the number of cylinders slightly wrong (in
1567 * the conservative direction). The idea is to be able 1567 * the conservative direction). The idea is to be able
1568 * to create a NetBSD partition on a disk we don't know 1568 * to create a NetBSD partition on a disk we don't know
1569 * the translated geometry of. 1569 * the translated geometry of.
1570 * This routine is only used for non-x86 systems or when we fail to 1570 * This routine is only used for non-x86 systems or when we fail to
1571 * get the BIOS geometry from the kernel. 1571 * get the BIOS geometry from the kernel.
1572 */ 1572 */
1573void 1573static void
1574intuit_translated_geometry(void) 1574intuit_translated_geometry(void)
1575{ 1575{
1576 uint32_t xcylinders; 1576 uint32_t xcylinders;
1577 int xheads = -1, xsectors = -1, i, j; 1577 int xheads = -1, xsectors = -1, i, j;
1578 unsigned int c1, h1, s1, c2, h2, s2; 1578 unsigned int c1, h1, s1, c2, h2, s2;
1579 unsigned long a1, a2; 1579 unsigned long a1, a2;
1580 uint64_t num, denom; 1580 uint64_t num, denom;
1581 1581
1582 /* 1582 /*
1583 * The physical parameters may be invalid as bios geometry. 1583 * The physical parameters may be invalid as bios geometry.
1584 * If we cannot determine the actual bios geometry, we are 1584 * If we cannot determine the actual bios geometry, we are
1585 * better off picking a likely 'faked' geometry than leaving 1585 * better off picking a likely 'faked' geometry than leaving
1586 * the invalid physical one. 1586 * the invalid physical one.
1587 */ 1587 */
1588 1588
1589 if (dos_cylinders > MAXCYL || dos_heads > MAXHEAD || 1589 if (dos_cylinders > MAXCYL || dos_heads > MAXHEAD ||
1590 dos_sectors > MAXSECTOR) { 1590 dos_sectors > MAXSECTOR) {
1591 h1 = MAXHEAD - 1; 1591 h1 = MAXHEAD - 1;
1592 c1 = MAXCYL - 1; 1592 c1 = MAXCYL - 1;
1593#if defined(USE_DISKLIST) 1593#if defined(USE_DISKLIST)
1594 if (dl != NULL) { 1594 if (dl != NULL) {
1595 /* BIOS may use 256 heads or 1024 cylinders */ 1595 /* BIOS may use 256 heads or 1024 cylinders */
1596 for (i = 0; i < dl->dl_nbiosdisks; i++) { 1596 for (i = 0; i < dl->dl_nbiosdisks; i++) {
1597 if (h1 < (unsigned int)dl->dl_biosdisks[i].bi_head) 1597 if (h1 < (unsigned int)dl->dl_biosdisks[i].bi_head)
1598 h1 = dl->dl_biosdisks[i].bi_head; 1598 h1 = dl->dl_biosdisks[i].bi_head;
1599 if (c1 < (unsigned int)dl->dl_biosdisks[i].bi_cyl) 1599 if (c1 < (unsigned int)dl->dl_biosdisks[i].bi_cyl)
1600 c1 = dl->dl_biosdisks[i].bi_cyl; 1600 c1 = dl->dl_biosdisks[i].bi_cyl;
1601 } 1601 }
1602 } 1602 }
1603#endif 1603#endif
1604 dos_sectors = MAXSECTOR; 1604 dos_sectors = MAXSECTOR;
1605 dos_heads = h1; 1605 dos_heads = h1;
1606 dos_cylinders = disklabel.d_secperunit / (MAXSECTOR * h1); 1606 dos_cylinders = disklabel.d_secperunit / (MAXSECTOR * h1);
1607 if (dos_cylinders > c1) 1607 if (dos_cylinders > c1)
1608 dos_cylinders = c1; 1608 dos_cylinders = c1;
1609 } 1609 }
1610 1610
1611 /* Try to deduce the number of heads from two different mappings. */ 1611 /* Try to deduce the number of heads from two different mappings. */
1612 for (i = 0; i < MBR_PART_COUNT * 2 - 1; i++) { 1612 for (i = 0; i < MBR_PART_COUNT * 2 - 1; i++) {
1613 if (get_mapping(i, &c1, &h1, &s1, &a1) < 0) 1613 if (get_mapping(i, &c1, &h1, &s1, &a1) < 0)
1614 continue; 1614 continue;
1615 a1 -= s1; 1615 a1 -= s1;
1616 for (j = i + 1; j < MBR_PART_COUNT * 2; j++) { 1616 for (j = i + 1; j < MBR_PART_COUNT * 2; j++) {
1617 if (get_mapping(j, &c2, &h2, &s2, &a2) < 0) 1617 if (get_mapping(j, &c2, &h2, &s2, &a2) < 0)
1618 continue; 1618 continue;
1619 a2 -= s2; 1619 a2 -= s2;
1620 num = (uint64_t)h1 * a2 - (uint64_t)h2 * a1; 1620 num = (uint64_t)h1 * a2 - (uint64_t)h2 * a1;
1621 denom = (uint64_t)c2 * a1 - (uint64_t)c1 * a2; 1621 denom = (uint64_t)c2 * a1 - (uint64_t)c1 * a2;
1622 if (denom != 0 && num != 0 && num % denom == 0) { 1622 if (denom != 0 && num != 0 && num % denom == 0) {
1623 xheads = num / denom; 1623 xheads = num / denom;
1624 xsectors = a1 / (c1 * xheads + h1); 1624 xsectors = a1 / (c1 * xheads + h1);
1625 break; 1625 break;
1626 } 1626 }
1627 } 1627 }
1628 if (xheads != -1)  1628 if (xheads != -1)
1629 break; 1629 break;
1630 } 1630 }
1631 1631
1632 if (xheads == -1) { 1632 if (xheads == -1) {
1633 warnx("Cannot determine the number of heads"); 1633 warnx("Cannot determine the number of heads");
1634 return; 1634 return;
1635 } 1635 }
1636 1636
1637 if (xsectors == -1) { 1637 if (xsectors == -1) {
1638 warnx("Cannot determine the number of sectors"); 1638 warnx("Cannot determine the number of sectors");
1639 return; 1639 return;
1640 } 1640 }
1641 1641
1642 /* Estimate the number of cylinders. */ 1642 /* Estimate the number of cylinders. */
1643 xcylinders = disklabel.d_secperunit / xheads / xsectors; 1643 xcylinders = disklabel.d_secperunit / xheads / xsectors;
1644 if (disklabel.d_secperunit > xcylinders * xheads * xsectors) 1644 if (disklabel.d_secperunit > xcylinders * xheads * xsectors)
1645 xcylinders++; 1645 xcylinders++;
1646 1646
1647 /* 1647 /*
1648 * Now verify consistency with each of the partition table entries. 1648 * Now verify consistency with each of the partition table entries.
1649 * Be willing to shove cylinders up a little bit to make things work, 1649 * Be willing to shove cylinders up a little bit to make things work,
1650 * but translation mismatches are fatal. 1650 * but translation mismatches are fatal.
1651 */ 1651 */
1652 for (i = 0; i < MBR_PART_COUNT * 2; i++) { 1652 for (i = 0; i < MBR_PART_COUNT * 2; i++) {
1653 if (get_mapping(i, &c1, &h1, &s1, &a1) < 0) 1653 if (get_mapping(i, &c1, &h1, &s1, &a1) < 0)
1654 continue; 1654 continue;
1655 if (c1 >= MAXCYL - 2) 1655 if (c1 >= MAXCYL - 2)
1656 continue; 1656 continue;
1657 if (xsectors * (c1 * xheads + h1) + s1 != a1) 1657 if (xsectors * (c1 * xheads + h1) + s1 != a1)
1658 return; 1658 return;
1659 } 1659 }
1660 1660
1661 1661
1662 /* Everything checks out. 1662 /* Everything checks out.
1663 * Reset the geometry to use for further calculations. 1663 * Reset the geometry to use for further calculations.
1664 * But cylinders cannot be > 1024. 1664 * But cylinders cannot be > 1024.
1665 */ 1665 */
1666 if (xcylinders > MAXCYL) 1666 if (xcylinders > MAXCYL)
1667 dos_cylinders = MAXCYL; 1667 dos_cylinders = MAXCYL;
1668 else 1668 else
1669 dos_cylinders = xcylinders; 1669 dos_cylinders = xcylinders;
1670 dos_heads = xheads; 1670 dos_heads = xheads;
1671 dos_sectors = xsectors; 1671 dos_sectors = xsectors;
1672} 1672}
1673 1673
1674/* 1674/*
1675 * For the purposes of intuit_translated_geometry(), treat the partition 1675 * For the purposes of intuit_translated_geometry(), treat the partition
1676 * table as a list of eight mapping between (cylinder, head, sector) 1676 * table as a list of eight mapping between (cylinder, head, sector)
1677 * triplets and absolute sectors. Get the relevant geometry triplet and 1677 * triplets and absolute sectors. Get the relevant geometry triplet and
1678 * absolute sectors for a given entry, or return -1 if it isn't present. 1678 * absolute sectors for a given entry, or return -1 if it isn't present.
1679 * Note: for simplicity, the returned sector is 0-based. 1679 * Note: for simplicity, the returned sector is 0-based.
1680 */ 1680 */
1681int 1681static int
1682get_mapping(int i, unsigned int *cylinder, unsigned int *head, unsigned int *sector, 1682get_mapping(int i, unsigned int *cylinder, unsigned int *head, unsigned int *sector,
1683 unsigned long *absolute) 1683 unsigned long *absolute)
1684{ 1684{
1685 struct mbr_partition *part = &mboot.mbr_parts[i / 2]; 1685 struct mbr_partition *part = &mboot.mbr_parts[i / 2];
1686 1686
1687 if (part->mbrp_type == 0) 1687 if (part->mbrp_type == 0)
1688 return -1; 1688 return -1;
1689 if (i % 2 == 0) { 1689 if (i % 2 == 0) {
1690 *cylinder = MBR_PCYL(part->mbrp_scyl, part->mbrp_ssect); 1690 *cylinder = MBR_PCYL(part->mbrp_scyl, part->mbrp_ssect);
1691 *head = part->mbrp_shd; 1691 *head = part->mbrp_shd;
1692 *sector = MBR_PSECT(part->mbrp_ssect); 1692 *sector = MBR_PSECT(part->mbrp_ssect);
1693 *absolute = le32toh(part->mbrp_start); 1693 *absolute = le32toh(part->mbrp_start);
1694 } else { 1694 } else {
1695 *cylinder = MBR_PCYL(part->mbrp_ecyl, part->mbrp_esect); 1695 *cylinder = MBR_PCYL(part->mbrp_ecyl, part->mbrp_esect);
1696 *head = part->mbrp_ehd; 1696 *head = part->mbrp_ehd;
1697 *sector = MBR_PSECT(part->mbrp_esect); 1697 *sector = MBR_PSECT(part->mbrp_esect);
1698 *absolute = le32toh(part->mbrp_start) 1698 *absolute = le32toh(part->mbrp_start)
1699 + le32toh(part->mbrp_size) - 1; 1699 + le32toh(part->mbrp_size) - 1;
1700 } 1700 }
1701 /* Sanity check the data against all zeroes */ 1701 /* Sanity check the data against all zeroes */
1702 if ((*cylinder == 0) && (*sector == 0) && (*head == 0)) 1702 if ((*cylinder == 0) && (*sector == 0) && (*head == 0))
1703 return -1; 1703 return -1;
1704 /* sector numbers in the MBR partition table start at 1 */ 1704 /* sector numbers in the MBR partition table start at 1 */
1705 *sector = *sector - 1; 1705 *sector = *sector - 1;
1706 /* Sanity check the data against max values */ 1706 /* Sanity check the data against max values */
1707 if ((((*cylinder * MAXHEAD) + *head) * MAXSECTOR + *sector) < *absolute) 1707 if ((((*cylinder * MAXHEAD) + *head) * MAXSECTOR + *sector) < *absolute)
1708 /* cannot be a CHS mapping */ 1708 /* cannot be a CHS mapping */
1709 return -1; 1709 return -1;
1710 return 0; 1710 return 0;
1711} 1711}
1712 1712
1713static void 1713static void
1714delete_ptn(int part) 1714delete_ptn(int part)
1715{ 1715{
1716 if (part == ext.ptn_id) { 1716 if (part == ext.ptn_id) {
1717 /* forget all about the extended partition */ 1717 /* forget all about the extended partition */
1718 free(ext.ptn); 1718 free(ext.ptn);
1719 memset(&ext, 0, sizeof ext); 1719 memset(&ext, 0, sizeof ext);
1720 } 1720 }
1721 1721
1722 mboot.mbr_parts[part].mbrp_type = 0; 1722 mboot.mbr_parts[part].mbrp_type = 0;
1723} 1723}
1724 1724
1725static void 1725static void
1726delete_ext_ptn(int part) 1726delete_ext_ptn(int part)
1727{ 1727{
1728 1728
1729 if (part == 0) { 1729 if (part == 0) {
1730 ext.ptn[0].mbr_parts[0].mbrp_type = 0; 1730 ext.ptn[0].mbr_parts[0].mbrp_type = 0;
1731 return; 1731 return;
1732 } 1732 }
1733 ext.ptn[part - 1].mbr_parts[1] = ext.ptn[part].mbr_parts[1]; 1733 ext.ptn[part - 1].mbr_parts[1] = ext.ptn[part].mbr_parts[1];
1734 memmove(&ext.ptn[part], &ext.ptn[part + 1], 1734 memmove(&ext.ptn[part], &ext.ptn[part + 1],
1735 (ext.num_ptn - part - 1) * sizeof ext.ptn[0]); 1735 (ext.num_ptn - part - 1) * sizeof ext.ptn[0]);
1736 ext.num_ptn--; 1736 ext.num_ptn--;
1737} 1737}
1738 1738
1739static int 1739static int
1740add_ext_ptn(daddr_t start, daddr_t size) 1740add_ext_ptn(daddr_t start, daddr_t size)
1741{ 1741{
1742 int part; 1742 int part;
1743 struct mbr_partition *partp; 1743 struct mbr_partition *partp;
1744 struct mbr_sector *nptn; 1744 struct mbr_sector *nptn;
1745 1745
1746 nptn = realloc(ext.ptn, (ext.num_ptn + 1) * sizeof *ext.ptn); 1746 nptn = realloc(ext.ptn, (ext.num_ptn + 1) * sizeof *ext.ptn);
1747 if (!nptn) 1747 if (!nptn)
1748 err(1, "realloc"); 1748 err(1, "realloc");
1749 ext.ptn = nptn; 1749 ext.ptn = nptn;
1750 for (part = 0; part < ext.num_ptn; part++) 1750 for (part = 0; part < ext.num_ptn; part++)
1751 if (ext_offset(part) > start) 1751 if (ext_offset(part) > start)
1752 break; 1752 break;
1753 /* insert before 'part' - make space... */ 1753 /* insert before 'part' - make space... */
1754 memmove(&ext.ptn[part + 1], &ext.ptn[part], 1754 memmove(&ext.ptn[part + 1], &ext.ptn[part],
1755 (ext.num_ptn - part) * sizeof ext.ptn[0]); 1755 (ext.num_ptn - part) * sizeof ext.ptn[0]);
1756 memset(&ext.ptn[part], 0, sizeof ext.ptn[0]); 1756 memset(&ext.ptn[part], 0, sizeof ext.ptn[0]);
1757 ext.ptn[part].mbr_magic = LE_MBR_MAGIC; 1757 ext.ptn[part].mbr_magic = LE_MBR_MAGIC;
1758 /* we will be 'part' */ 1758 /* we will be 'part' */
1759 if (part == 0) { 1759 if (part == 0) {
1760 /* link us to 'next' */ 1760 /* link us to 'next' */
1761 partp = &ext.ptn[0].mbr_parts[1]; 1761 partp = &ext.ptn[0].mbr_parts[1];
1762 /* offset will be fixed by caller */ 1762 /* offset will be fixed by caller */
1763 partp->mbrp_size = htole32( 1763 partp->mbrp_size = htole32(
1764 le32toh(ext.ptn[1].mbr_parts[0].mbrp_start) + 1764 le32toh(ext.ptn[1].mbr_parts[0].mbrp_start) +
1765 le32toh(ext.ptn[1].mbr_parts[0].mbrp_size)); 1765 le32toh(ext.ptn[1].mbr_parts[0].mbrp_size));
1766 } else { 1766 } else {
1767 /* link us to prev's next */ 1767 /* link us to prev's next */
1768 partp = &ext.ptn[part - 1].mbr_parts[1]; 1768 partp = &ext.ptn[part - 1].mbr_parts[1];
1769 ext.ptn[part].mbr_parts[1] = *partp; 1769 ext.ptn[part].mbr_parts[1] = *partp;
1770 /* and prev onto us */ 1770 /* and prev onto us */
1771 partp->mbrp_start = htole32(start - ptn_0_offset - ext.base); 1771 partp->mbrp_start = htole32(start - ptn_0_offset - ext.base);
1772 partp->mbrp_size = htole32(size + ptn_0_offset); 1772 partp->mbrp_size = htole32(size + ptn_0_offset);
1773 } 1773 }
1774 partp->mbrp_type = 5; /* as used by win98 */ 1774 partp->mbrp_type = 5; /* as used by win98 */
1775 partp->mbrp_flag = 0; 1775 partp->mbrp_flag = 0;
1776 /* wallop in some CHS values - win98 doesn't saturate them */ 1776 /* wallop in some CHS values - win98 doesn't saturate them */
1777 dos(le32toh(partp->mbrp_start), 1777 dos(le32toh(partp->mbrp_start),
1778 &partp->mbrp_scyl, &partp->mbrp_shd, &partp->mbrp_ssect); 1778 &partp->mbrp_scyl, &partp->mbrp_shd, &partp->mbrp_ssect);
1779 dos(le32toh(partp->mbrp_start) + le32toh(partp->mbrp_size) - 1, 1779 dos(le32toh(partp->mbrp_start) + le32toh(partp->mbrp_size) - 1,
1780 &partp->mbrp_ecyl, &partp->mbrp_ehd, &partp->mbrp_esect); 1780 &partp->mbrp_ecyl, &partp->mbrp_ehd, &partp->mbrp_esect);
1781 ext.num_ptn++; 1781 ext.num_ptn++;
1782 1782
1783 return part; 1783 return part;
1784} 1784}
1785 1785
1786static const char * 1786static const char *
1787check_overlap(int part, int sysid, daddr_t start, daddr_t size, int fix) 1787check_overlap(int part, int sysid, daddr_t start, daddr_t size, int fix)
1788{ 1788{
1789 int p; 1789 int p;
1790 unsigned int p_s, p_e; 1790 unsigned int p_s, p_e;
1791 1791
1792 if (sysid != 0) { 1792 if (sysid != 0) {
1793 if (start == 0) 1793 if (start == 0)
1794 return "Sector zero is reserved for the MBR"; 1794 return "Sector zero is reserved for the MBR";
1795#if 0 1795#if 0
1796 if (start < ptn_0_offset) 1796 if (start < ptn_0_offset)
1797 /* This is just a convention, not a requirement */ 1797 /* This is just a convention, not a requirement */
1798 return "Track zero is reserved for the BIOS"; 1798 return "Track zero is reserved for the BIOS";
1799#endif 1799#endif
1800 if (start + size > disksectors)  1800 if (start + size > disksectors)
1801 return "Partition exceeds size of disk"; 1801 return "Partition exceeds size of disk";
1802 for (p = 0; p < MBR_PART_COUNT; p++) { 1802 for (p = 0; p < MBR_PART_COUNT; p++) {
1803 if (p == part || mboot.mbr_parts[p].mbrp_type == 0) 1803 if (p == part || mboot.mbr_parts[p].mbrp_type == 0)
1804 continue; 1804 continue;
1805 p_s = le32toh(mboot.mbr_parts[p].mbrp_start); 1805 p_s = le32toh(mboot.mbr_parts[p].mbrp_start);
1806 p_e = p_s + le32toh(mboot.mbr_parts[p].mbrp_size); 1806 p_e = p_s + le32toh(mboot.mbr_parts[p].mbrp_size);
1807 if (start + size <= p_s || start >= p_e) 1807 if (start + size <= p_s || start >= p_e)
1808 continue; 1808 continue;
1809 if (f_flag) { 1809 if (f_flag) {
1810 if (fix) 1810 if (fix)
1811 delete_ptn(p); 1811 delete_ptn(p);
1812 return 0; 1812 return 0;
1813 } 1813 }
1814 return "Overlaps another partition"; 1814 return "Overlaps another partition";
1815 } 1815 }
1816 } 1816 }
1817 1817
1818 /* Are we trying to create an extended partition */ 1818 /* Are we trying to create an extended partition */
1819 if (!MBR_IS_EXTENDED(mboot.mbr_parts[part].mbrp_type)) { 1819 if (!MBR_IS_EXTENDED(mboot.mbr_parts[part].mbrp_type)) {
1820 /* this wasn't the extended partition */ 1820 /* this wasn't the extended partition */
1821 if (!MBR_IS_EXTENDED(sysid)) 1821 if (!MBR_IS_EXTENDED(sysid))
1822 return 0; 1822 return 0;
1823 /* making an extended partition */ 1823 /* making an extended partition */
1824 if (ext.base != 0) { 1824 if (ext.base != 0) {
1825 if (!f_flag) 1825 if (!f_flag)
1826 return "There cannot be 2 extended partitions"; 1826 return "There cannot be 2 extended partitions";
1827 if (fix) 1827 if (fix)
1828 delete_ptn(ext.ptn_id); 1828 delete_ptn(ext.ptn_id);
1829 } 1829 }
1830 if (fix) { 1830 if (fix) {
1831 /* allocate a new extended partition */ 1831 /* allocate a new extended partition */
1832 ext.ptn = calloc(1, sizeof ext.ptn[0]); 1832 ext.ptn = calloc(1, sizeof ext.ptn[0]);
1833 if (ext.ptn == NULL) 1833 if (ext.ptn == NULL)
1834 err(1, "Malloc failed"); 1834 err(1, "Malloc failed");
1835 ext.ptn[0].mbr_magic = LE_MBR_MAGIC; 1835 ext.ptn[0].mbr_magic = LE_MBR_MAGIC;
1836 ext.ptn_id = part; 1836 ext.ptn_id = part;
1837 ext.base = start; 1837 ext.base = start;
1838 ext.limit = start + size; 1838 ext.limit = start + size;
1839 ext.num_ptn = 1; 1839 ext.num_ptn = 1;
1840 } 1840 }
1841 return 0; 1841 return 0;
1842 } 1842 }
1843 1843
1844 /* Check we haven't cut space allocated to an extended ptn */ 1844 /* Check we haven't cut space allocated to an extended ptn */
1845  1845
1846 if (!MBR_IS_EXTENDED(sysid)) { 1846 if (!MBR_IS_EXTENDED(sysid)) {
1847 /* no longer an extended partition */ 1847 /* no longer an extended partition */
1848 if (fix) { 1848 if (fix) {
1849 /* Kill all memory of the extended partitions */ 1849 /* Kill all memory of the extended partitions */
1850 delete_ptn(part); 1850 delete_ptn(part);
1851 return 0; 1851 return 0;
1852 } 1852 }
1853 if (ext.num_ptn == 0 || 1853 if (ext.num_ptn == 0 ||
1854 (ext.num_ptn == 1 && ext.ptn[0].mbr_parts[0].mbrp_type == 0)) 1854 (ext.num_ptn == 1 && ext.ptn[0].mbr_parts[0].mbrp_type == 0))
1855 /* nothing in extended partition */ 1855 /* nothing in extended partition */
1856 return 0; 1856 return 0;
1857 if (f_flag) 1857 if (f_flag)
1858 return 0; 1858 return 0;
1859 if (yesno("Do you really want to delete all the extended partitions?")) 1859 if (yesno("Do you really want to delete all the extended partitions?"))
1860 return 0; 1860 return 0;
1861 return "Extended partition busy"; 1861 return "Extended partition busy";
1862 } 1862 }
1863 1863
1864 if (le32toh(mboot.mbr_parts[part].mbrp_start) != ext.base) 1864 if (le32toh(mboot.mbr_parts[part].mbrp_start) != ext.base)
1865 /* maybe impossible, but an extra sanity check */ 1865 /* maybe impossible, but an extra sanity check */
1866 return 0; 1866 return 0;
1867 1867
1868 for (p = ext.num_ptn; --p >= 0;) { 1868 for (p = ext.num_ptn; --p >= 0;) {
1869 if (ext.ptn[p].mbr_parts[0].mbrp_type == 0) 1869 if (ext.ptn[p].mbr_parts[0].mbrp_type == 0)
1870 continue; 1870 continue;
1871 p_s = ext_offset(p); 1871 p_s = ext_offset(p);
1872 p_e = p_s + le32toh(ext.ptn[p].mbr_parts[0].mbrp_start) 1872 p_e = p_s + le32toh(ext.ptn[p].mbr_parts[0].mbrp_start)
1873 + le32toh(ext.ptn[p].mbr_parts[0].mbrp_size); 1873 + le32toh(ext.ptn[p].mbr_parts[0].mbrp_size);
1874 if (p_s >= start && p_e <= start + size) 1874 if (p_s >= start && p_e <= start + size)
1875 continue; 1875 continue;
1876 if (!f_flag) 1876 if (!f_flag)
1877 return "Extended partition outside main partition"; 1877 return "Extended partition outside main partition";
1878 if (fix) 1878 if (fix)
1879 delete_ext_ptn(p); 1879 delete_ext_ptn(p);
1880 } 1880 }
1881 1881
1882 if (fix && start != ext.base) { 1882 if (fix && start != ext.base) {
1883 /* The internal offsets need to be fixed up */ 1883 /* The internal offsets need to be fixed up */
1884 for (p = 0; p < ext.num_ptn - 1; p++) 1884 for (p = 0; p < ext.num_ptn - 1; p++)
1885 ext.ptn[p].mbr_parts[1].mbrp_start = htole32( 1885 ext.ptn[p].mbr_parts[1].mbrp_start = htole32(
1886 le32toh(ext.ptn[p].mbr_parts[1].mbrp_start) 1886 le32toh(ext.ptn[p].mbr_parts[1].mbrp_start)
1887 + ext.base - start); 1887 + ext.base - start);
1888 /* and maybe an empty partition at the start */ 1888 /* and maybe an empty partition at the start */
1889 if (ext.ptn[0].mbr_parts[0].mbrp_type == 0) { 1889 if (ext.ptn[0].mbr_parts[0].mbrp_type == 0) {
1890 if (le32toh(ext.ptn[0].mbr_parts[1].mbrp_start) == 0) { 1890 if (le32toh(ext.ptn[0].mbr_parts[1].mbrp_start) == 0) {
1891 /* don't need the empty slot */ 1891 /* don't need the empty slot */
1892 memmove(&ext.ptn[0], &ext.ptn[1], 1892 memmove(&ext.ptn[0], &ext.ptn[1],
1893 (ext.num_ptn - 1) * sizeof ext.ptn[0]); 1893 (ext.num_ptn - 1) * sizeof ext.ptn[0]);
1894 ext.num_ptn--; 1894 ext.num_ptn--;
1895 } 1895 }
1896 } else { 1896 } else {
1897 /* must create an empty slot */ 1897 /* must create an empty slot */
1898 add_ext_ptn(start, ptn_0_offset); 1898 add_ext_ptn(start, ptn_0_offset);
1899 ext.ptn[0].mbr_parts[1].mbrp_start = htole32(ext.base 1899 ext.ptn[0].mbr_parts[1].mbrp_start = htole32(ext.base
1900 - start); 1900 - start);
1901 } 1901 }
1902 } 1902 }
1903 if (fix) { 1903 if (fix) {
1904 ext.base = start; 1904 ext.base = start;
1905 ext.limit = start + size; 1905 ext.limit = start + size;
1906 } 1906 }
1907 return 0; 1907 return 0;
1908} 1908}
1909 1909
1910static const char * 1910static const char *
1911check_ext_overlap(int part, int sysid, daddr_t start, daddr_t size, int fix) 1911check_ext_overlap(int part, int sysid, daddr_t start, daddr_t size, int fix)
1912{ 1912{
1913 int p; 1913 int p;
1914 unsigned int p_s, p_e; 1914 unsigned int p_s, p_e;
1915 1915
1916 if (sysid == 0) 1916 if (sysid == 0)
1917 return 0; 1917 return 0;
1918 1918
1919 if (MBR_IS_EXTENDED(sysid)) 1919 if (MBR_IS_EXTENDED(sysid))
1920 return "Nested extended partitions are not allowed"; 1920 return "Nested extended partitions are not allowed";
1921 1921
1922 /* allow one track at start for extended partition header */ 1922 /* allow one track at start for extended partition header */
1923 start -= ptn_0_offset; 1923 start -= ptn_0_offset;
1924 size += ptn_0_offset; 1924 size += ptn_0_offset;
1925 if (start < ext.base || start + size > ext.limit) 1925 if (start < ext.base || start + size > ext.limit)
1926 return "Outside bounds of extended partition"; 1926 return "Outside bounds of extended partition";
1927 1927
1928 if (f_flag && !fix) 1928 if (f_flag && !fix)
1929 return 0; 1929 return 0;
1930 1930
1931 for (p = ext.num_ptn; --p >= 0;) { 1931 for (p = ext.num_ptn; --p >= 0;) {
1932 if (p == part || ext.ptn[p].mbr_parts[0].mbrp_type == 0) 1932 if (p == part || ext.ptn[p].mbr_parts[0].mbrp_type == 0)
1933 continue; 1933 continue;
1934 p_s = ext_offset(p); 1934 p_s = ext_offset(p);
1935 p_e = p_s + le32toh(ext.ptn[p].mbr_parts[0].mbrp_start) 1935 p_e = p_s + le32toh(ext.ptn[p].mbr_parts[0].mbrp_start)
1936 + le32toh(ext.ptn[p].mbr_parts[0].mbrp_size); 1936 + le32toh(ext.ptn[p].mbr_parts[0].mbrp_size);
1937 if (p == 0) 1937 if (p == 0)
1938 p_s += le32toh(ext.ptn[p].mbr_parts[0].mbrp_start) 1938 p_s += le32toh(ext.ptn[p].mbr_parts[0].mbrp_start)
1939 - ptn_0_offset; 1939 - ptn_0_offset;
1940 if (start < p_e && start + size > p_s) { 1940 if (start < p_e && start + size > p_s) {
1941 if (!f_flag) 1941 if (!f_flag)
1942 return "Overlaps another extended partition"; 1942 return "Overlaps another extended partition";
1943 if (fix) { 1943 if (fix) {
1944 if (part == -1) 1944 if (part == -1)
1945 delete_ext_ptn(p); 1945 delete_ext_ptn(p);
1946 else 1946 else
1947 /* must not change numbering yet */ 1947 /* must not change numbering yet */
1948 ext.ptn[p].mbr_parts[0].mbrp_type = 0; 1948 ext.ptn[p].mbr_parts[0].mbrp_type = 0;
1949 } 1949 }
1950 } 1950 }
1951 } 1951 }
1952 return 0; 1952 return 0;
1953} 1953}
1954 1954
1955int 1955static int
1956change_part(int extended, int part, int sysid, daddr_t start, daddr_t size, 1956change_part(int extended, int part, int sysid, daddr_t start, daddr_t size,
1957 char *bootmenu) 1957 char *bootmenu)
1958{ 1958{
1959 struct mbr_partition *partp; 1959 struct mbr_partition *partp;
1960 struct mbr_sector *boot; 1960 struct mbr_sector *boot;
1961 daddr_t offset; 1961 daddr_t offset;
1962 const char *e; 1962 const char *e;
1963 int upart = part; 1963 int upart = part;
1964 int p; 1964 int p;
1965 int fl; 1965 int fl;
1966 daddr_t n_s, n_e; 1966 daddr_t n_s, n_e;
1967 const char *errtext; 1967 const char *errtext;
1968#ifdef BOOTSEL 1968#ifdef BOOTSEL
1969 char tmp_bootmenu[MBR_PART_COUNT * (MBR_BS_PARTNAMESIZE + 1)]; 1969 char tmp_bootmenu[MBR_PART_COUNT * (MBR_BS_PARTNAMESIZE + 1)];
1970 int bootmenu_len = (extended ? MBR_PART_COUNT : 1) * (MBR_BS_PARTNAMESIZE + 1); 1970 int bootmenu_len = (extended ? MBR_PART_COUNT : 1) * (MBR_BS_PARTNAMESIZE + 1);
1971#endif 1971#endif
1972 1972
1973 if (extended) { 1973 if (extended) {
1974 if (part != -1 && part < ext.num_ptn) { 1974 if (part != -1 && part < ext.num_ptn) {
1975 boot = &ext.ptn[part]; 1975 boot = &ext.ptn[part];
1976 partp = &boot->mbr_parts[0]; 1976 partp = &boot->mbr_parts[0];
1977 offset = ext_offset(part); 1977 offset = ext_offset(part);
1978 } else { 1978 } else {
1979 part = -1; 1979 part = -1;
1980 boot = 0; 1980 boot = 0;
1981 partp = 0; 1981 partp = 0;
1982 offset = 0; 1982 offset = 0;
1983 } 1983 }
1984 upart = 0; 1984 upart = 0;
1985 e = "E"; 1985 e = "E";
1986 } else { 1986 } else {
1987 boot = &mboot; 1987 boot = &mboot;
1988 partp = &boot->mbr_parts[part]; 1988 partp = &boot->mbr_parts[part];
1989 offset = 0; 1989 offset = 0;
1990 e = ""; 1990 e = "";
1991 } 1991 }
1992 1992
1993 if (!f_flag && part != -1) { 1993 if (!f_flag && part != -1) {
1994 printf("The data for partition %s%d is:\n", e, part); 1994 printf("The data for partition %s%d is:\n", e, part);
1995 print_part(boot, upart, offset); 1995 print_part(boot, upart, offset);
1996 } 1996 }
1997 1997
1998#ifdef BOOTSEL 1998#ifdef BOOTSEL
1999 if (bootmenu != NULL) 1999 if (bootmenu != NULL)
2000 strlcpy(tmp_bootmenu, bootmenu, bootmenu_len); 2000 strlcpy(tmp_bootmenu, bootmenu, bootmenu_len);
2001 else 2001 else
2002 if (boot != NULL && boot->mbr_bootsel_magic == LE_MBR_BS_MAGIC) 2002 if (boot != NULL && boot->mbr_bootsel_magic == LE_MBR_BS_MAGIC)
2003 strlcpy(tmp_bootmenu, 2003 strlcpy(tmp_bootmenu,
2004 boot->mbr_bootsel.mbrbs_nametab[upart], 2004 boot->mbr_bootsel.mbrbs_nametab[upart],
2005 bootmenu_len); 2005 bootmenu_len);
2006 else 2006 else
2007 tmp_bootmenu[0] = 0; 2007 tmp_bootmenu[0] = 0;
2008#endif 2008#endif
2009 2009
2010 if (!s_flag && partp != NULL) { 2010 if (!s_flag && partp != NULL) {
2011 /* values not specified, default to current ones */ 2011 /* values not specified, default to current ones */
2012 sysid = partp->mbrp_type; 2012 sysid = partp->mbrp_type;
2013 start = offset + le32toh(partp->mbrp_start); 2013 start = offset + le32toh(partp->mbrp_start);
2014 size = le32toh(partp->mbrp_size); 2014 size = le32toh(partp->mbrp_size);
2015 } 2015 }
2016 2016
2017 /* creating a new partition, default to free space */ 2017 /* creating a new partition, default to free space */
2018 if (!s_flag && sysid == 0 && extended) { 2018 if (!s_flag && sysid == 0 && extended) {
2019 /* non-extended partition */ 2019 /* non-extended partition */
2020 start = ext.base; 2020 start = ext.base;
2021 for (p = 0; p < ext.num_ptn; p++) { 2021 for (p = 0; p < ext.num_ptn; p++) {
2022 if (ext.ptn[p].mbr_parts[0].mbrp_type == 0) 2022 if (ext.ptn[p].mbr_parts[0].mbrp_type == 0)
2023 continue; 2023 continue;
2024 n_s = ext_offset(p); 2024 n_s = ext_offset(p);
2025 if (n_s > start + ptn_0_offset) 2025 if (n_s > start + ptn_0_offset)
2026 break; 2026 break;
2027 start = ext_offset(p) 2027 start = ext_offset(p)
2028 + le32toh(ext.ptn[p].mbr_parts[0].mbrp_start) 2028 + le32toh(ext.ptn[p].mbr_parts[0].mbrp_start)
2029 + le32toh(ext.ptn[p].mbr_parts[0].mbrp_size); 2029 + le32toh(ext.ptn[p].mbr_parts[0].mbrp_size);
2030 } 2030 }
2031 if (ext.limit - start <= ptn_0_offset) { 2031 if (ext.limit - start <= ptn_0_offset) {
2032 printf("No space in extended partition\n"); 2032 printf("No space in extended partition\n");
2033 return 0; 2033 return 0;
2034 } 2034 }
2035 start += ptn_0_offset; 2035 start += ptn_0_offset;
2036 } 2036 }
2037 2037
2038 if (!s_flag && sysid == 0 && !extended) { 2038 if (!s_flag && sysid == 0 && !extended) {
2039 /* same for non-extended partition */ 2039 /* same for non-extended partition */
2040 /* first see if old start is free */ 2040 /* first see if old start is free */
2041 if (start < ptn_0_offset) 2041 if (start < ptn_0_offset)
2042 start = 0; 2042 start = 0;
2043 for (p = 0; start != 0 && p < MBR_PART_COUNT; p++) { 2043 for (p = 0; start != 0 && p < MBR_PART_COUNT; p++) {
2044 if (mboot.mbr_parts[p].mbrp_type == 0) 2044 if (mboot.mbr_parts[p].mbrp_type == 0)
2045 continue; 2045 continue;
2046 n_s = le32toh(mboot.mbr_parts[p].mbrp_start); 2046 n_s = le32toh(mboot.mbr_parts[p].mbrp_start);
2047 if (start >= n_s && 2047 if (start >= n_s &&
2048 start < n_s + le32toh(mboot.mbr_parts[p].mbrp_size)) 2048 start < n_s + le32toh(mboot.mbr_parts[p].mbrp_size))
2049 start = 0; 2049 start = 0;
2050 } 2050 }
2051 if (start == 0) { 2051 if (start == 0) {
2052 /* Look for first gap */ 2052 /* Look for first gap */
2053 start = ptn_0_offset; 2053 start = ptn_0_offset;
2054 for (p = 0; p < MBR_PART_COUNT; p++) { 2054 for (p = 0; p < MBR_PART_COUNT; p++) {
2055 if (mboot.mbr_parts[p].mbrp_type == 0) 2055 if (mboot.mbr_parts[p].mbrp_type == 0)
2056 continue; 2056 continue;
2057 n_s = le32toh(mboot.mbr_parts[p].mbrp_start); 2057 n_s = le32toh(mboot.mbr_parts[p].mbrp_start);
2058 n_e = n_s + le32toh(mboot.mbr_parts[p].mbrp_size); 2058 n_e = n_s + le32toh(mboot.mbr_parts[p].mbrp_size);
2059 if (start >= n_s && start < n_e) { 2059 if (start >= n_s && start < n_e) {
2060 start = n_e; 2060 start = n_e;
2061 p = -1; 2061 p = -1;
2062 } 2062 }
2063 } 2063 }
2064 if (start >= disksectors) { 2064 if (start >= disksectors) {
2065 printf("No free space\n"); 2065 printf("No free space\n");
2066 return 0; 2066 return 0;
2067 } 2067 }
2068 } 2068 }
2069 } 2069 }
2070 2070
2071 if (!f_flag) { 2071 if (!f_flag) {
2072 /* request new values from user */ 2072 /* request new values from user */
2073 if (sysid == 0) 2073 if (sysid == 0)
2074 sysid = 169; 2074 sysid = 169;
2075 sysid = decimal("sysid", sysid, 0, 0, 255); 2075 sysid = decimal("sysid", sysid, 0, 0, 255);
2076 if (sysid == 0 && !v_flag) { 2076 if (sysid == 0 && !v_flag) {
2077 start = 0; 2077 start = 0;
2078 size = 0; 2078 size = 0;
2079#ifdef BOOTSEL 2079#ifdef BOOTSEL
2080 tmp_bootmenu[0] = 0; 2080 tmp_bootmenu[0] = 0;
2081#endif 2081#endif
2082 } else { 2082 } else {
2083 daddr_t old = start; 2083 daddr_t old = start;
2084 daddr_t lim = extended ? ext.limit : disksectors; 2084 daddr_t lim = extended ? ext.limit : disksectors;
2085 start = decimal("start", start, 2085 start = decimal("start", start,
2086 DEC_SEC | DEC_RND_0 | (extended ? DEC_RND : 0), 2086 DEC_SEC | DEC_RND_0 | (extended ? DEC_RND : 0),
2087 extended ? ext.base : 0, lim); 2087 extended ? ext.base : 0, lim);
2088 /* Adjust 'size' so that end doesn't move when 'start' 2088 /* Adjust 'size' so that end doesn't move when 'start'
2089 * is only changed slightly. 2089 * is only changed slightly.
2090 */ 2090 */
2091 if (size > start - old) 2091 if (size > start - old)
2092 size -= start - old; 2092 size -= start - old;
2093 else 2093 else
2094 size = 0; 2094 size = 0;
2095 /* Find end of available space from this start point */ 2095 /* Find end of available space from this start point */
2096 if (extended) { 2096 if (extended) {
2097 for (p = 0; p < ext.num_ptn; p++) { 2097 for (p = 0; p < ext.num_ptn; p++) {
2098 if (p == part) 2098 if (p == part)
2099 continue; 2099 continue;
2100 if (ext.ptn[p].mbr_parts[0].mbrp_type == 0) 2100 if (ext.ptn[p].mbr_parts[0].mbrp_type == 0)
2101 continue; 2101 continue;
2102 n_s = ext_offset(p); 2102 n_s = ext_offset(p);
2103 if (n_s > start && n_s < lim) 2103 if (n_s > start && n_s < lim)
2104 lim = n_s; 2104 lim = n_s;
2105 if (start >= n_s && start < n_s 2105 if (start >= n_s && start < n_s
2106 + le32toh(ext.ptn[p].mbr_parts[0].mbrp_start) 2106 + le32toh(ext.ptn[p].mbr_parts[0].mbrp_start)
2107 + le32toh(ext.ptn[p].mbr_parts[0].mbrp_size)) { 2107 + le32toh(ext.ptn[p].mbr_parts[0].mbrp_size)) {
2108 lim = start; 2108 lim = start;
2109 break; 2109 break;
2110 } 2110 }
2111 } 2111 }
2112 } else { 2112 } else {
2113 for (p = 0; p < MBR_PART_COUNT; p++) { 2113 for (p = 0; p < MBR_PART_COUNT; p++) {
2114 if (p == part) 2114 if (p == part)
2115 continue; 2115 continue;
2116 if (mboot.mbr_parts[p].mbrp_type == 0) 2116 if (mboot.mbr_parts[p].mbrp_type == 0)
2117 continue; 2117 continue;
2118 n_s = le32toh(mboot.mbr_parts[p].mbrp_start); 2118 n_s = le32toh(mboot.mbr_parts[p].mbrp_start);
2119 if (n_s > start && n_s < lim) 2119 if (n_s > start && n_s < lim)
2120 lim = n_s; 2120 lim = n_s;
2121 if (start >= n_s && start < n_s 2121 if (start >= n_s && start < n_s
2122 + le32toh(mboot.mbr_parts[p].mbrp_size)) { 2122 + le32toh(mboot.mbr_parts[p].mbrp_size)) {
2123 lim = start; 2123 lim = start;
2124 break; 2124 break;
2125 } 2125 }
2126 } 2126 }
2127 } 2127 }
2128 lim -= start; 2128 lim -= start;
2129 if (lim == 0) { 2129 if (lim == 0) {
2130 printf("Start sector already allocated\n"); 2130 printf("Start sector already allocated\n");
2131 return 0; 2131 return 0;
2132 } 2132 }
2133 if (size == 0 || size > lim) 2133 if (size == 0 || size > lim)
2134 size = lim; 2134 size = lim;
2135 fl = DEC_SEC; 2135 fl = DEC_SEC;
2136 if (start % ptn_alignment == ptn_0_offset) 2136 if (start % ptn_alignment == ptn_0_offset)
2137 fl |= DEC_RND_DOWN; 2137 fl |= DEC_RND_DOWN;
2138 if (start == 2 * ptn_0_offset) 2138 if (start == 2 * ptn_0_offset)
2139 fl |= DEC_RND_DOWN | DEC_RND_DOWN_2; 2139 fl |= DEC_RND_DOWN | DEC_RND_DOWN_2;
2140 size = decimal("size", size, fl, 0, lim); 2140 size = decimal("size", size, fl, 0, lim);
2141#ifdef BOOTSEL 2141#ifdef BOOTSEL
2142#ifndef DEFAULT_BOOTEXTCODE 2142#ifndef DEFAULT_BOOTEXTCODE
2143 if (!extended) 2143 if (!extended)
2144#endif 2144#endif
2145 string("bootmenu", bootmenu_len, tmp_bootmenu); 2145 string("bootmenu", bootmenu_len, tmp_bootmenu);
2146#endif 2146#endif
2147 } 2147 }
2148 } 2148 }
2149 2149
2150 /* 2150 /*
2151 * Before we write these away, we must verify that nothing 2151 * Before we write these away, we must verify that nothing
2152 * untoward has been requested. 2152 * untoward has been requested.
2153 */ 2153 */
2154 2154
2155 if (extended) 2155 if (extended)
2156 errtext = check_ext_overlap(part, sysid, start, size, 0); 2156 errtext = check_ext_overlap(part, sysid, start, size, 0);
2157 else 2157 else
2158 errtext = check_overlap(part, sysid, start, size, 0); 2158 errtext = check_overlap(part, sysid, start, size, 0);
2159 if (errtext != NULL) { 2159 if (errtext != NULL) {
2160 if (f_flag) 2160 if (f_flag)
2161 errx(2, "%s\n", errtext); 2161 errx(2, "%s\n", errtext);
2162 printf("%s\n", errtext); 2162 printf("%s\n", errtext);
2163 return 0; 2163 return 0;
2164 } 2164 }
2165 2165
2166 /* 2166 /*
2167 * Before proceeding, delete any overlapped partitions. 2167 * Before proceeding, delete any overlapped partitions.
2168 * This can only happen if '-f' was supplied on the command line. 2168 * This can only happen if '-f' was supplied on the command line.
2169 * Just hope the caller knows what they are doing. 2169 * Just hope the caller knows what they are doing.
2170 * This also fixes the base of each extended partition if the 2170 * This also fixes the base of each extended partition if the
2171 * partition itself has moved. 2171 * partition itself has moved.
2172 */ 2172 */
2173 2173
2174 if (extended) 2174 if (extended)
2175 errtext = check_ext_overlap(part, sysid, start, size, 1); 2175 errtext = check_ext_overlap(part, sysid, start, size, 1);
2176 else 2176 else
2177 errtext = check_overlap(part, sysid, start, size, 1); 2177 errtext = check_overlap(part, sysid, start, size, 1);
2178 2178
2179 if (errtext) 2179 if (errtext)
2180 errx(1, "%s\n", errtext); 2180 errx(1, "%s\n", errtext);
2181 2181
2182 if (sysid == 0) { 2182 if (sysid == 0) {
2183 /* delete this partition - save info though */ 2183 /* delete this partition - save info though */
2184 if (partp == NULL) 2184 if (partp == NULL)
2185 /* must have been trying to create an extended ptn */ 2185 /* must have been trying to create an extended ptn */
2186 return 0; 2186 return 0;
2187 if (start == 0 && size == 0) 2187 if (start == 0 && size == 0)
2188 memset(partp, 0, sizeof *partp); 2188 memset(partp, 0, sizeof *partp);
2189#ifdef BOOTSEL 2189#ifdef BOOTSEL
2190 if (boot->mbr_bootsel_magic == LE_MBR_BS_MAGIC) 2190 if (boot->mbr_bootsel_magic == LE_MBR_BS_MAGIC)
2191 memset(boot->mbr_bootsel.mbrbs_nametab[upart], 0, 2191 memset(boot->mbr_bootsel.mbrbs_nametab[upart], 0,
2192 sizeof boot->mbr_bootsel.mbrbs_nametab[0]); 2192 sizeof boot->mbr_bootsel.mbrbs_nametab[0]);
2193#endif 2193#endif
2194 if (extended) 2194 if (extended)
2195 delete_ext_ptn(part); 2195 delete_ext_ptn(part);
2196 else 2196 else
2197 delete_ptn(part); 2197 delete_ptn(part);
2198 return 1; 2198 return 1;
2199 } 2199 }
2200 2200
2201 2201
2202 if (extended) { 2202 if (extended) {
2203 if (part != -1) 2203 if (part != -1)
2204 delete_ext_ptn(part); 2204 delete_ext_ptn(part);
2205 if (start == ext.base + ptn_0_offset) 2205 if (start == ext.base + ptn_0_offset)
2206 /* First one must have been free */ 2206 /* First one must have been free */
2207 part = 0; 2207 part = 0;
2208 else 2208 else
2209 part = add_ext_ptn(start, size); 2209 part = add_ext_ptn(start, size);
2210 2210
2211 /* These must be re-calculated because of the realloc */ 2211 /* These must be re-calculated because of the realloc */
2212 boot = &ext.ptn[part]; 2212 boot = &ext.ptn[part];
2213 partp = &boot->mbr_parts[0]; 2213 partp = &boot->mbr_parts[0];
2214 offset = ext_offset(part); 2214 offset = ext_offset(part);
2215 } 2215 }
2216 2216
2217 partp->mbrp_type = sysid; 2217 partp->mbrp_type = sysid;
2218 partp->mbrp_start = htole32( start - offset); 2218 partp->mbrp_start = htole32( start - offset);
2219 partp->mbrp_size = htole32( size); 2219 partp->mbrp_size = htole32( size);
2220 dos(start, &partp->mbrp_scyl, &partp->mbrp_shd, &partp->mbrp_ssect); 2220 dos(start, &partp->mbrp_scyl, &partp->mbrp_shd, &partp->mbrp_ssect);
2221 dos(start + size - 1, 2221 dos(start + size - 1,
2222 &partp->mbrp_ecyl, &partp->mbrp_ehd, &partp->mbrp_esect); 2222 &partp->mbrp_ecyl, &partp->mbrp_ehd, &partp->mbrp_esect);
2223#ifdef BOOTSEL 2223#ifdef BOOTSEL
2224 if (extended) { 2224 if (extended) {
2225 boot->mbr_bootsel_magic = LE_MBR_BS_MAGIC; 2225 boot->mbr_bootsel_magic = LE_MBR_BS_MAGIC;
2226 strncpy(boot->mbr_bootsel.mbrbs_nametab[upart], tmp_bootmenu, 2226 strncpy(boot->mbr_bootsel.mbrbs_nametab[upart], tmp_bootmenu,
2227 bootmenu_len); 2227 bootmenu_len);
2228 } else { 2228 } else {
2229 /* We need to bootselect code installed in order to have 2229 /* We need to bootselect code installed in order to have
2230 * somewhere to safely write the menu tag. 2230 * somewhere to safely write the menu tag.
2231 */ 2231 */
2232 if (boot->mbr_bootsel_magic != LE_MBR_BS_MAGIC) { 2232 if (boot->mbr_bootsel_magic != LE_MBR_BS_MAGIC) {
2233 if (f_flag || 2233 if (f_flag ||
2234 yesno("The bootselect code is not installed, " 2234 yesno("The bootselect code is not installed, "
2235 "do you want to install it now?")) 2235 "do you want to install it now?"))
2236 install_bootsel(MBR_BS_ACTIVE); 2236 install_bootsel(MBR_BS_ACTIVE);
2237 } 2237 }
2238 if (boot->mbr_bootsel_magic == LE_MBR_BS_MAGIC) { 2238 if (boot->mbr_bootsel_magic == LE_MBR_BS_MAGIC) {
2239 strncpy(boot->mbr_bootsel.mbrbs_nametab[upart], 2239 strncpy(boot->mbr_bootsel.mbrbs_nametab[upart],
2240 tmp_bootmenu, bootmenu_len); 2240 tmp_bootmenu, bootmenu_len);
2241 } 2241 }
2242 } 2242 }
2243#endif 2243#endif
2244 2244
2245 if (v_flag && !f_flag && yesno("Explicitly specify beg/end address?")) { 2245 if (v_flag && !f_flag && yesno("Explicitly specify beg/end address?")) {
2246 /* this really isn't a good idea.... */ 2246 /* this really isn't a good idea.... */
2247 int tsector, tcylinder, thead; 2247 int tsector, tcylinder, thead;
2248 2248
2249 tcylinder = MBR_PCYL(partp->mbrp_scyl, partp->mbrp_ssect); 2249 tcylinder = MBR_PCYL(partp->mbrp_scyl, partp->mbrp_ssect);
2250 thead = partp->mbrp_shd; 2250 thead = partp->mbrp_shd;
2251 tsector = MBR_PSECT(partp->mbrp_ssect); 2251 tsector = MBR_PSECT(partp->mbrp_ssect);
2252 tcylinder = decimal("beginning cylinder", 2252 tcylinder = decimal("beginning cylinder",
2253 tcylinder, 0, 0, dos_cylinders - 1); 2253 tcylinder, 0, 0, dos_cylinders - 1);
2254 thead = decimal("beginning head", 2254 thead = decimal("beginning head",
2255 thead, 0, 0, dos_heads - 1); 2255 thead, 0, 0, dos_heads - 1);
2256 tsector = decimal("beginning sector", 2256 tsector = decimal("beginning sector",
2257 tsector, 0, 1, dos_sectors); 2257 tsector, 0, 1, dos_sectors);
2258 partp->mbrp_scyl = DOSCYL(tcylinder); 2258 partp->mbrp_scyl = DOSCYL(tcylinder);
2259 partp->mbrp_shd = thead; 2259 partp->mbrp_shd = thead;
2260 partp->mbrp_ssect = DOSSECT(tsector, tcylinder); 2260 partp->mbrp_ssect = DOSSECT(tsector, tcylinder);
2261 2261
2262 tcylinder = MBR_PCYL(partp->mbrp_ecyl, partp->mbrp_esect); 2262 tcylinder = MBR_PCYL(partp->mbrp_ecyl, partp->mbrp_esect);
2263 thead = partp->mbrp_ehd; 2263 thead = partp->mbrp_ehd;
2264 tsector = MBR_PSECT(partp->mbrp_esect); 2264 tsector = MBR_PSECT(partp->mbrp_esect);
2265 tcylinder = decimal("ending cylinder", 2265 tcylinder = decimal("ending cylinder",
2266 tcylinder, 0, 0, dos_cylinders - 1); 2266 tcylinder, 0, 0, dos_cylinders - 1);
2267 thead = decimal("ending head", 2267 thead = decimal("ending head",
2268 thead, 0, 0, dos_heads - 1); 2268 thead, 0, 0, dos_heads - 1);
2269 tsector = decimal("ending sector", 2269 tsector = decimal("ending sector",
2270 tsector, 0, 1, dos_sectors); 2270 tsector, 0, 1, dos_sectors);
2271 partp->mbrp_ecyl = DOSCYL(tcylinder); 2271 partp->mbrp_ecyl = DOSCYL(tcylinder);
2272 partp->mbrp_ehd = thead; 2272 partp->mbrp_ehd = thead;
2273 partp->mbrp_esect = DOSSECT(tsector, tcylinder); 2273 partp->mbrp_esect = DOSSECT(tsector, tcylinder);
2274 } 2274 }
2275 2275
2276 /* If we had to mark an extended partition as deleted because 2276 /* If we had to mark an extended partition as deleted because
2277 * another request would have overlapped it, now is the time 2277 * another request would have overlapped it, now is the time
2278 * to do the actual delete. 2278 * to do the actual delete.
2279 */ 2279 */
2280 if (extended && f_flag) { 2280 if (extended && f_flag) {
2281 for (p = ext.num_ptn; --p >= 0;) 2281 for (p = ext.num_ptn; --p >= 0;)
2282 if (ext.ptn[p].mbr_parts[0].mbrp_type == 0) 2282 if (ext.ptn[p].mbr_parts[0].mbrp_type == 0)
2283 delete_ext_ptn(p); 2283 delete_ext_ptn(p);
2284 } 2284 }
2285 return 1; 2285 return 1;
2286} 2286}
2287 2287
2288void 2288static void
2289print_geometry(void) 2289print_geometry(void)
2290{ 2290{
2291 2291
2292 if (sh_flag) { 2292 if (sh_flag) {
2293 printf("DISK=%s\n", disk); 2293 printf("DISK=%s\n", disk);
2294 printf("DLCYL=%d\nDLHEAD=%d\nDLSEC=%d\nDLSIZE=%"PRIdaddr"\n", 2294 printf("DLCYL=%d\nDLHEAD=%d\nDLSEC=%d\nDLSIZE=%"PRIdaddr"\n",
2295 cylinders, heads, sectors, disksectors); 2295 cylinders, heads, sectors, disksectors);
2296 printf("BCYL=%d\nBHEAD=%d\nBSEC=%d\nBDLSIZE=%"PRIdaddr"\n", 2296 printf("BCYL=%d\nBHEAD=%d\nBSEC=%d\nBDLSIZE=%"PRIdaddr"\n",
2297 dos_cylinders, dos_heads, dos_sectors, dos_disksectors); 2297 dos_cylinders, dos_heads, dos_sectors, dos_disksectors);
2298 printf("NUMEXTPTN=%d\n", ext.num_ptn); 2298 printf("NUMEXTPTN=%d\n", ext.num_ptn);
2299 return; 2299 return;
2300 } 2300 }
2301 2301
2302 /* Not sh_flag */ 2302 /* Not sh_flag */
2303 printf("Disk: %s\n", disk); 2303 printf("Disk: %s\n", disk);
2304 printf("NetBSD disklabel disk geometry:\n"); 2304 printf("NetBSD disklabel disk geometry:\n");
2305 printf("cylinders: %d, heads: %d, sectors/track: %d " 2305 printf("cylinders: %d, heads: %d, sectors/track: %d "
2306 "(%d sectors/cylinder)\ntotal sectors: %"PRIdaddr"\n\n", 2306 "(%d sectors/cylinder)\ntotal sectors: %"PRIdaddr"\n\n",
2307 cylinders, heads, sectors, cylindersectors, disksectors); 2307 cylinders, heads, sectors, cylindersectors, disksectors);
2308 printf("BIOS disk geometry:\n"); 2308 printf("BIOS disk geometry:\n");
2309 printf("cylinders: %d, heads: %d, sectors/track: %d " 2309 printf("cylinders: %d, heads: %d, sectors/track: %d "
2310 "(%d sectors/cylinder)\ntotal sectors: %"PRIdaddr"\n\n", 2310 "(%d sectors/cylinder)\ntotal sectors: %"PRIdaddr"\n\n",
2311 dos_cylinders, dos_heads, dos_sectors, dos_cylindersectors, 2311 dos_cylinders, dos_heads, dos_sectors, dos_cylindersectors,
2312 dos_disksectors); 2312 dos_disksectors);
2313 printf("Partitions aligned to %d sector boundaries, offset %d\n\n", 2313 printf("Partitions aligned to %d sector boundaries, offset %d\n\n",
2314 ptn_alignment, ptn_0_offset); 2314 ptn_alignment, ptn_0_offset);
2315} 2315}
2316 2316
2317/* Find the first active partition, else return MBR_PART_COUNT */ 2317/* Find the first active partition, else return MBR_PART_COUNT */
2318int 2318static int
2319first_active(void) 2319first_active(void)
2320{ 2320{
2321 struct mbr_partition *partp = &mboot.mbr_parts[0]; 2321 struct mbr_partition *partp = &mboot.mbr_parts[0];
2322 int part; 2322 int part;
2323 2323
2324 for (part = 0; part < MBR_PART_COUNT; part++) 2324 for (part = 0; part < MBR_PART_COUNT; part++)
2325 if (partp[part].mbrp_flag & MBR_PFLAG_ACTIVE) 2325 if (partp[part].mbrp_flag & MBR_PFLAG_ACTIVE)
2326 return part; 2326 return part;
2327 return MBR_PART_COUNT; 2327 return MBR_PART_COUNT;
2328} 2328}
2329 2329
2330void 2330static void
2331change_active(int which) 2331change_active(int which)
2332{ 2332{
2333 struct mbr_partition *partp; 2333 struct mbr_partition *partp;
2334 int part; 2334 int part;
2335 int active = MBR_PART_COUNT; 2335 int active = MBR_PART_COUNT;
2336 2336
2337 partp = &mboot.mbr_parts[0]; 2337 partp = &mboot.mbr_parts[0];
2338 2338
2339 if (a_flag && which != -1) 2339 if (a_flag && which != -1)
2340 active = which; 2340 active = which;
2341 else 2341 else
2342 active = first_active(); 2342 active = first_active();
2343 if (!f_flag) { 2343 if (!f_flag) {
2344 if (yesno("Do you want to change the active partition?")) { 2344 if (yesno("Do you want to change the active partition?")) {
2345 printf ("Choosing %d will make no partition active.\n", 2345 printf ("Choosing %d will make no partition active.\n",
2346 MBR_PART_COUNT); 2346 MBR_PART_COUNT);
2347 do { 2347 do {
2348 active = decimal("active partition", 2348 active = decimal("active partition",
2349 active, 0, 0, MBR_PART_COUNT); 2349 active, 0, 0, MBR_PART_COUNT);
2350 } while (!yesno("Are you happy with this choice?")); 2350 } while (!yesno("Are you happy with this choice?"));
2351 } else 2351 } else
2352 return; 2352 return;
2353 } else 2353 } else
2354 if (active != MBR_PART_COUNT) 2354 if (active != MBR_PART_COUNT)
2355 printf ("Making partition %d active.\n", active); 2355 printf ("Making partition %d active.\n", active);
2356 2356
2357 for (part = 0; part < MBR_PART_COUNT; part++) 2357 for (part = 0; part < MBR_PART_COUNT; part++)
2358 partp[part].mbrp_flag &= ~MBR_PFLAG_ACTIVE; 2358 partp[part].mbrp_flag &= ~MBR_PFLAG_ACTIVE;
2359 if (active < MBR_PART_COUNT) 2359 if (active < MBR_PART_COUNT)
2360 partp[active].mbrp_flag |= MBR_PFLAG_ACTIVE; 2360 partp[active].mbrp_flag |= MBR_PFLAG_ACTIVE;
2361} 2361}
2362 2362
2363void 2363static void
2364change_bios_geometry(void) 2364change_bios_geometry(void)
2365{ 2365{
2366 print_geometry(); 2366 print_geometry();
2367 if (!yesno("Do you want to change our idea of what BIOS thinks?")) 2367 if (!yesno("Do you want to change our idea of what BIOS thinks?"))
2368 return; 2368 return;
2369 2369
2370#if defined(USE_DISKLIST) 2370#if defined(USE_DISKLIST)
2371 if (dl != NULL) { 2371 if (dl != NULL) {
2372 struct biosdisk_info *bip; 2372 struct biosdisk_info *bip;
2373 int i; 2373 int i;
2374 2374
2375 for (i = 0; i < dl->dl_nbiosdisks; i++) { 2375 for (i = 0; i < dl->dl_nbiosdisks; i++) {
2376 if (i == 0) 2376 if (i == 0)
2377 printf("\nGeometries of known disks:\n"); 2377 printf("\nGeometries of known disks:\n");
2378 bip = &dl->dl_biosdisks[i]; 2378 bip = &dl->dl_biosdisks[i];
2379 printf("Disk %d: cylinders %u, heads %u, sectors %u" 2379 printf("Disk %d: cylinders %u, heads %u, sectors %u"
2380 " (%"PRIdaddr" sectors, %dMB)\n", 2380 " (%"PRIdaddr" sectors, %dMB)\n",
2381 i, bip->bi_cyl, bip->bi_head, bip->bi_sec, 2381 i, bip->bi_cyl, bip->bi_head, bip->bi_sec,
2382 bip->bi_lbasecs, SEC_TO_MB(bip->bi_lbasecs)); 2382 bip->bi_lbasecs, SEC_TO_MB(bip->bi_lbasecs));
2383  2383
2384 } 2384 }
2385 printf("\n"); 2385 printf("\n");
2386 } 2386 }
2387#endif 2387#endif
2388 do { 2388 do {
2389 dos_cylinders = decimal("BIOS's idea of #cylinders", 2389 dos_cylinders = decimal("BIOS's idea of #cylinders",
2390 dos_cylinders, 0, 0, MAXCYL); 2390 dos_cylinders, 0, 0, MAXCYL);
2391 dos_heads = decimal("BIOS's idea of #heads", 2391 dos_heads = decimal("BIOS's idea of #heads",
2392 dos_heads, 0, 0, MAXHEAD); 2392 dos_heads, 0, 0, MAXHEAD);
2393 dos_sectors = decimal("BIOS's idea of #sectors", 2393 dos_sectors = decimal("BIOS's idea of #sectors",
2394 dos_sectors, 0, 1, MAXSECTOR); 2394 dos_sectors, 0, 1, MAXSECTOR);
2395 print_geometry(); 2395 print_geometry();
2396 } while (!yesno("Are you happy with this choice?")); 2396 } while (!yesno("Are you happy with this choice?"));
2397} 2397}
2398 2398
2399 2399
2400/***********************************************\ 2400/***********************************************\
2401* Change real numbers into strange dos numbers * 2401* Change real numbers into strange dos numbers *
2402\***********************************************/ 2402\***********************************************/
2403void 2403static void
2404dos(int sector, unsigned char *cylinderp, unsigned char *headp, 2404dos(int sector, unsigned char *cylinderp, unsigned char *headp,
2405 unsigned char *sectorp) 2405 unsigned char *sectorp)
2406{ 2406{
2407 int cylinder, head; 2407 int cylinder, head;
2408 2408
2409 cylinder = sector / dos_cylindersectors; 2409 cylinder = sector / dos_cylindersectors;
2410 sector -= cylinder * dos_cylindersectors; 2410 sector -= cylinder * dos_cylindersectors;
2411 2411
2412 head = sector / dos_sectors; 2412 head = sector / dos_sectors;
2413 sector -= head * dos_sectors; 2413 sector -= head * dos_sectors;
2414 if (cylinder > 1023) 2414 if (cylinder > 1023)
2415 cylinder = 1023; 2415 cylinder = 1023;
2416 2416
2417 *cylinderp = DOSCYL(cylinder); 2417 *cylinderp = DOSCYL(cylinder);
2418 *headp = head; 2418 *headp = head;
2419 *sectorp = DOSSECT(sector + 1, cylinder); 2419 *sectorp = DOSSECT(sector + 1, cylinder);
2420} 2420}
2421 2421
2422int 2422static int
2423open_disk(int update) 2423open_disk(int update)
2424{ 2424{
2425 static char namebuf[MAXPATHLEN + 1]; 2425 static char namebuf[MAXPATHLEN + 1];
2426 int flags = update && disk_file == NULL ? O_RDWR : O_RDONLY; 2426 int flags = update && disk_file == NULL ? O_RDWR : O_RDONLY;
2427 2427
2428 if (!F_flag) { 2428 if (!F_flag) {
2429 fd = opendisk(disk, flags, namebuf, sizeof(namebuf), 0); 2429 fd = opendisk(disk, flags, namebuf, sizeof(namebuf), 0);
2430 if (fd < 0) { 2430 if (fd < 0) {
2431 if (errno == ENODEV) 2431 if (errno == ENODEV)
2432 warnx("%s is not a character device", namebuf); 2432 warnx("%s is not a character device", namebuf);
2433 else 2433 else
2434 warn("cannot opendisk %s", namebuf); 2434 warn("cannot opendisk %s", namebuf);
2435 return (-1); 2435 return (-1);
2436 } 2436 }
2437 disk = namebuf; 2437 disk = namebuf;
2438 } else { 2438 } else {
2439 fd = open(disk, flags, 0); 2439 fd = open(disk, flags, 0);
2440 if (fd == -1) { 2440 if (fd == -1) {
2441 warn("cannot open %s", disk); 2441 warn("cannot open %s", disk);
2442 return -1; 2442 return -1;
2443 } 2443 }
2444 } 2444 }
2445 2445
2446 if (get_params() == -1) { 2446 if (get_params() == -1) {
2447 close(fd); 2447 close(fd);
2448 fd = -1; 2448 fd = -1;
2449 return (-1); 2449 return (-1);
2450 } 2450 }
2451 if (disk_file != NULL) { 2451 if (disk_file != NULL) {
2452 /* for testing: read/write data from a disk file */ 2452 /* for testing: read/write data from a disk file */
2453 wfd = open(disk_file, update ? O_RDWR|O_CREAT : O_RDONLY, 0777); 2453 wfd = open(disk_file, update ? O_RDWR|O_CREAT : O_RDONLY, 0777);
2454 if (wfd == -1) { 2454 if (wfd == -1) {
2455 warn("%s", disk_file); 2455 warn("%s", disk_file);
2456 close(fd); 2456 close(fd);
2457 fd = -1; 2457 fd = -1;
2458 return -1; 2458 return -1;
2459 } 2459 }
2460 } else 2460 } else
2461 wfd = fd; 2461 wfd = fd;
2462 return (0); 2462 return (0);
2463} 2463}
2464 2464
2465int 2465static int
2466read_disk(daddr_t sector, void *buf) 2466read_disk(daddr_t sector, void *buf)
2467{ 2467{
2468 2468
2469 if (*rfd == -1) 2469 if (*rfd == -1)
2470 errx(1, "read_disk(); fd == -1"); 2470 errx(1, "read_disk(); fd == -1");
2471 if (lseek(*rfd, sector * (off_t)512, 0) == -1) 2471 if (lseek(*rfd, sector * (off_t)512, 0) == -1)
2472 return (-1); 2472 return (-1);
2473 return (read(*rfd, buf, 512)); 2473 return (read(*rfd, buf, 512));
2474} 2474}
2475 2475
2476int 2476static int
2477write_disk(daddr_t sector, void *buf) 2477write_disk(daddr_t sector, void *buf)
2478{ 2478{
2479 2479
2480 if (wfd == -1) 2480 if (wfd == -1)
2481 errx(1, "write_disk(); wfd == -1"); 2481 errx(1, "write_disk(); wfd == -1");
2482 if (lseek(wfd, sector * (off_t)512, 0) == -1) 2482 if (lseek(wfd, sector * (off_t)512, 0) == -1)
2483 return (-1); 2483 return (-1);
2484 return (write(wfd, buf, 512)); 2484 return (write(wfd, buf, 512));
2485} 2485}
2486 2486
2487static void 2487static void
2488guess_geometry(daddr_t _sectors) 2488guess_geometry(daddr_t _sectors)
2489{ 2489{
2490 dos_sectors = MAXSECTOR; 2490 dos_sectors = MAXSECTOR;
2491 dos_heads = MAXHEAD - 1; /* some BIOS might use 256 */ 2491 dos_heads = MAXHEAD - 1; /* some BIOS might use 256 */
2492 dos_cylinders = _sectors / (MAXSECTOR * (MAXHEAD - 1)); 2492 dos_cylinders = _sectors / (MAXSECTOR * (MAXHEAD - 1));
2493 if (dos_cylinders < 1) 2493 if (dos_cylinders < 1)
2494 dos_cylinders = 1; 2494 dos_cylinders = 1;
2495 else if (dos_cylinders > MAXCYL - 1) 2495 else if (dos_cylinders > MAXCYL - 1)
2496 dos_cylinders = MAXCYL - 1; 2496 dos_cylinders = MAXCYL - 1;
2497} 2497}
2498 2498
2499int 2499static int
2500get_params(void) 2500get_params(void)
2501{ 2501{
2502 if (disk_type != NULL) { 2502 if (disk_type != NULL) {
2503 struct disklabel *tmplabel; 2503 struct disklabel *tmplabel;
2504 2504
2505 if ((tmplabel = getdiskbyname(disk_type)) == NULL) { 2505 if ((tmplabel = getdiskbyname(disk_type)) == NULL) {
2506 warn("bad disktype"); 2506 warn("bad disktype");
2507 return (-1); 2507 return (-1);
2508 } 2508 }
2509 disklabel = *tmplabel; 2509 disklabel = *tmplabel;
2510 } else if (F_flag) { 2510 } else if (F_flag) {
2511 struct stat st; 2511 struct stat st;
2512 if (fstat(fd, &st) == -1) { 2512 if (fstat(fd, &st) == -1) {
2513 warn("fstat"); 2513 warn("fstat");
2514 return (-1); 2514 return (-1);
2515 } 2515 }
2516 if (st.st_size % 512 != 0) { 2516 if (st.st_size % 512 != 0) {
2517 warnx("%s size (%lld) is not divisible " 2517 warnx("%s size (%lld) is not divisible "
2518 "by sector size (%d)", disk, (long long)st.st_size, 2518 "by sector size (%d)", disk, (long long)st.st_size,
2519 512); 2519 512);
2520 } 2520 }
2521 disklabel.d_secperunit = st.st_size / 512; 2521 disklabel.d_secperunit = st.st_size / 512;
2522 guess_geometry(disklabel.d_secperunit); 2522 guess_geometry(disklabel.d_secperunit);
2523 disklabel.d_ncylinders = dos_cylinders; 2523 disklabel.d_ncylinders = dos_cylinders;
2524 disklabel.d_ntracks = dos_heads; 2524 disklabel.d_ntracks = dos_heads;
2525 disklabel.d_nsectors = dos_sectors; 2525 disklabel.d_nsectors = dos_sectors;
2526 } else if (ioctl(fd, DIOCGDEFLABEL, &disklabel) == -1) { 2526 } else if (ioctl(fd, DIOCGDEFLABEL, &disklabel) == -1) {
2527 warn("DIOCGDEFLABEL"); 2527 warn("DIOCGDEFLABEL");
2528 if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) { 2528 if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) {
2529 warn("DIOCGDINFO"); 2529 warn("DIOCGDINFO");
2530 return (-1); 2530 return (-1);
2531 } 2531 }
2532 } 2532 }
2533 2533
2534 disksectors = disklabel.d_secperunit; 2534 disksectors = disklabel.d_secperunit;
2535 cylinders = disklabel.d_ncylinders; 2535 cylinders = disklabel.d_ncylinders;
2536 heads = disklabel.d_ntracks; 2536 heads = disklabel.d_ntracks;
2537 sectors = disklabel.d_nsectors; 2537 sectors = disklabel.d_nsectors;
2538 2538
2539 /* pick up some defaults for the BIOS sizes */ 2539 /* pick up some defaults for the BIOS sizes */
2540 if (sectors <= MAXSECTOR) { 2540 if (sectors <= MAXSECTOR) {
2541 dos_cylinders = cylinders; 2541 dos_cylinders = cylinders;
2542 dos_heads = heads; 2542 dos_heads = heads;
2543 dos_sectors = sectors; 2543 dos_sectors = sectors;
2544 } else { 2544 } else {
2545 /* guess - has to better than the above */ 2545 /* guess - has to better than the above */
2546 guess_geometry(disksectors); 2546 guess_geometry(disksectors);
2547 } 2547 }
2548 dos_disksectors = disksectors; 2548 dos_disksectors = disksectors;
2549 2549
2550 return (0); 2550 return (0);
2551} 2551}
2552 2552
2553#ifdef BOOTSEL 2553#ifdef BOOTSEL
2554/* 2554/*
2555 * Rather unfortunately the bootsel 'magic' number is at the end of the 2555 * Rather unfortunately the bootsel 'magic' number is at the end of the
2556 * the structure, and there is no checksum. So when other operating 2556 * the structure, and there is no checksum. So when other operating
2557 * systems install mbr code by only writing the length of their code they 2557 * systems install mbr code by only writing the length of their code they
2558 * can overwrite part of the structure but keeping the magic number intact. 2558 * can overwrite part of the structure but keeping the magic number intact.
2559 * This code attempts to empirically detect this problem. 2559 * This code attempts to empirically detect this problem.
2560 */ 2560 */
2561static int 2561static int
2562validate_bootsel(struct mbr_bootsel *mbs) 2562validate_bootsel(struct mbr_bootsel *mbs)
2563{ 2563{
2564 unsigned int key = mbs->mbrbs_defkey; 2564 unsigned int key = mbs->mbrbs_defkey;
2565 unsigned int tmo; 2565 unsigned int tmo;
2566 size_t i; 2566 size_t i;
2567 2567
2568 if (v_flag) 2568 if (v_flag)
2569 return 0; 2569 return 0;
2570 2570
2571 /* 2571 /*
2572 * Check default key is sane 2572 * Check default key is sane
2573 * - this is the most likely field to be stuffed 2573 * - this is the most likely field to be stuffed
2574 * 16 disks and 16 bootable partitions seems enough! 2574 * 16 disks and 16 bootable partitions seems enough!
2575 * (the keymap decode starts falling apart at that point) 2575 * (the keymap decode starts falling apart at that point)
2576 */ 2576 */
2577 if (mbs->mbrbs_flags & MBR_BS_ASCII) { 2577 if (mbs->mbrbs_flags & MBR_BS_ASCII) {
2578 if (key != 0 && !(key == '\r' 2578 if (key != 0 && !(key == '\r'
2579 || (key >= '1' && key < '1' + MAX_BIOS_DISKS) 2579 || (key >= '1' && key < '1' + MAX_BIOS_DISKS)
2580 || (key >= 'a' && key < 'a' + MAX_BIOS_DISKS))) 2580 || (key >= 'a' && key < 'a' + MAX_BIOS_DISKS)))
2581 return 1; 2581 return 1;
2582 } else { 2582 } else {
2583 if (key != 0 && !(key == SCAN_ENTER 2583 if (key != 0 && !(key == SCAN_ENTER
2584 || (key >= SCAN_1 && key < SCAN_1 + MAX_BIOS_DISKS) 2584 || (key >= SCAN_1 && key < SCAN_1 + MAX_BIOS_DISKS)
2585 || (key >= SCAN_F1 && key < SCAN_F1 + MAX_BIOS_DISKS))) 2585 || (key >= SCAN_F1 && key < SCAN_F1 + MAX_BIOS_DISKS)))
2586 return 1; 2586 return 1;
2587 } 2587 }
2588 2588
2589 /* Checking the flags will lead to breakage... */ 2589 /* Checking the flags will lead to breakage... */
2590 2590
2591 /* Timeout value is expected to be a multiple of a second */ 2591 /* Timeout value is expected to be a multiple of a second */
2592 tmo = htole16(mbs->mbrbs_timeo); 2592 tmo = htole16(mbs->mbrbs_timeo);
2593 if (tmo != 0 && tmo != 0xffff && tmo != (10 * tmo + 9) / 182 * 182 / 10) 2593 if (tmo != 0 && tmo != 0xffff && tmo != (10 * tmo + 9) / 182 * 182 / 10)
2594 return 2; 2594 return 2;
2595 2595
2596 /* Check the menu strings are printable */ 2596 /* Check the menu strings are printable */
2597 /* Unfortunately they aren't zero filled... */ 2597 /* Unfortunately they aren't zero filled... */
2598 for (i = 0; i < sizeof(mbs->mbrbs_nametab); i++) { 2598 for (i = 0; i < sizeof(mbs->mbrbs_nametab); i++) {
2599 int c = (uint8_t)mbs->mbrbs_nametab[0][i]; 2599 int c = (uint8_t)mbs->mbrbs_nametab[0][i];
2600 if (c == 0 || isprint(c)) 2600 if (c == 0 || isprint(c))
2601 continue; 2601 continue;
2602 return 3; 2602 return 3;
2603 } 2603 }
2604 2604
2605 return 0; 2605 return 0;
2606} 2606}
2607#endif 2607#endif
2608 2608
2609int 2609static int
2610read_s0(daddr_t offset, struct mbr_sector *boot) 2610read_s0(daddr_t offset, struct mbr_sector *boot)
2611{ 2611{
2612 const char *tabletype = offset ? "extended" : "primary"; 2612 const char *tabletype = offset ? "extended" : "primary";
2613#ifdef BOOTSEL 2613#ifdef BOOTSEL
2614 static int reported; 2614 static int reported;
2615#endif 2615#endif
2616 2616
2617 if (read_disk(offset, boot) == -1) { 2617 if (read_disk(offset, boot) == -1) {
2618 warn("Can't read %s partition table", tabletype); 2618 warn("Can't read %s partition table", tabletype);
2619 return -1; 2619 return -1;
2620 } 2620 }
2621 if (boot->mbr_magic != LE_MBR_MAGIC) { 2621 if (boot->mbr_magic != LE_MBR_MAGIC) {
2622 warnx("%s partition table invalid, " 2622 warnx("%s partition table invalid, "
2623 "no magic in sector %"PRIdaddr, tabletype, offset); 2623 "no magic in sector %"PRIdaddr, tabletype, offset);
2624 return -1; 2624 return -1;
2625 2625
2626 } 2626 }
2627#ifdef BOOTSEL 2627#ifdef BOOTSEL
2628 if (boot->mbr_bootsel_magic == LE_MBR_BS_MAGIC) { 2628 if (boot->mbr_bootsel_magic == LE_MBR_BS_MAGIC) {
2629 /* mbr_bootsel in new location */ 2629 /* mbr_bootsel in new location */
2630 if (validate_bootsel(&boot->mbr_bootsel)) { 2630 if (validate_bootsel(&boot->mbr_bootsel)) {
2631 warnx("removing corrupt bootsel information"); 2631 warnx("removing corrupt bootsel information");
2632 boot->mbr_bootsel_magic = 0; 2632 boot->mbr_bootsel_magic = 0;
2633 } 2633 }
2634 return 0; 2634 return 0;
2635 } 2635 }
2636 if (boot->mbr_bootsel_magic != LE_MBR_MAGIC) 2636 if (boot->mbr_bootsel_magic != LE_MBR_MAGIC)
2637 return 0; 2637 return 0;
2638 2638
2639 /* mbr_bootsel in old location */ 2639 /* mbr_bootsel in old location */
2640 if (!reported) 2640 if (!reported)
2641 warnx("%s partition table: using old-style bootsel information", 2641 warnx("%s partition table: using old-style bootsel information",
2642 tabletype); 2642 tabletype);
2643 reported = 1; 2643 reported = 1;
2644 if (validate_bootsel((void *)((uint8_t *)boot + MBR_BS_OFFSET + 4))) { 2644 if (validate_bootsel((void *)((uint8_t *)boot + MBR_BS_OFFSET + 4))) {
2645 warnx("%s bootsel information corrupt - ignoring", tabletype); 2645 warnx("%s bootsel information corrupt - ignoring", tabletype);
2646 return 0; 2646 return 0;
2647 } 2647 }
2648 memmove((uint8_t *)boot + MBR_BS_OFFSET, 2648 memmove((uint8_t *)boot + MBR_BS_OFFSET,
2649 (uint8_t *)boot + MBR_BS_OFFSET + 4, 2649 (uint8_t *)boot + MBR_BS_OFFSET + 4,
2650 sizeof(struct mbr_bootsel)); 2650 sizeof(struct mbr_bootsel));
2651 if ( ! (boot->mbr_bootsel.mbrbs_flags & MBR_BS_NEWMBR)) { 2651 if ( ! (boot->mbr_bootsel.mbrbs_flags & MBR_BS_NEWMBR)) {
2652 /* old style default key */ 2652 /* old style default key */
2653 int id; 2653 int id;
2654 /* F1..F4 => ptn 0..3, F5+ => disk 0+ */ 2654 /* F1..F4 => ptn 0..3, F5+ => disk 0+ */
2655 id = boot->mbr_bootsel.mbrbs_defkey; 2655 id = boot->mbr_bootsel.mbrbs_defkey;
2656 id -= SCAN_F1; 2656 id -= SCAN_F1;
2657 if (id >= MBR_PART_COUNT) 2657 if (id >= MBR_PART_COUNT)
2658 id -= MBR_PART_COUNT; /* Use number of disk */ 2658 id -= MBR_PART_COUNT; /* Use number of disk */
2659 else if (mboot.mbr_parts[id].mbrp_type != 0) 2659 else if (mboot.mbr_parts[id].mbrp_type != 0)
2660 id = le32toh(boot->mbr_parts[id].mbrp_start); 2660 id = le32toh(boot->mbr_parts[id].mbrp_start);
2661 else 2661 else
2662 id = DEFAULT_ACTIVE; 2662 id = DEFAULT_ACTIVE;
2663 boot->mbr_bootsel.mbrbs_defkey = id; 2663 boot->mbr_bootsel.mbrbs_defkey = id;
2664 } 2664 }
2665 boot->mbr_bootsel_magic = LE_MBR_BS_MAGIC; 2665 boot->mbr_bootsel_magic = LE_MBR_BS_MAGIC;
2666 /* highlight that new bootsel code is necessary */ 2666 /* highlight that new bootsel code is necessary */
2667 boot->mbr_bootsel.mbrbs_flags &= ~MBR_BS_NEWMBR; 2667 boot->mbr_bootsel.mbrbs_flags &= ~MBR_BS_NEWMBR;
2668#endif /* BOOTSEL */ 2668#endif /* BOOTSEL */
2669 return 0; 2669 return 0;
2670} 2670}
2671 2671
2672int 2672static int
2673write_mbr(void) 2673write_mbr(void)
2674{ 2674{
2675 int flag, i; 2675 int flag, i;
2676 daddr_t offset; 2676 daddr_t offset;
2677 int rval = -1; 2677 int rval = -1;
2678 2678
2679 /* 2679 /*
2680 * write enable label sector before write (if necessary), 2680 * write enable label sector before write (if necessary),
2681 * disable after writing. 2681 * disable after writing.
2682 * needed if the disklabel protected area also protects 2682 * needed if the disklabel protected area also protects
2683 * sector 0. (e.g. empty disk) 2683 * sector 0. (e.g. empty disk)
2684 */ 2684 */
2685 flag = 1; 2685 flag = 1;
2686 if (wfd == fd && F_flag == 0 && ioctl(wfd, DIOCWLABEL, &flag) < 0) 2686 if (wfd == fd && F_flag == 0 && ioctl(wfd, DIOCWLABEL, &flag) < 0)
2687 warn("DIOCWLABEL"); 2687 warn("DIOCWLABEL");
2688 if (write_disk(0, &mboot) == -1) { 2688 if (write_disk(0, &mboot) == -1) {
2689 warn("Can't write fdisk partition table"); 2689 warn("Can't write fdisk partition table");
2690 goto protect_label; 2690 goto protect_label;
2691 } 2691 }
2692 if (boot_installed) 2692 if (boot_installed)
2693 for (i = bootsize; (i -= 0x200) > 0;) 2693 for (i = bootsize; (i -= 0x200) > 0;)
2694 if (write_disk(i / 0x200, &bootcode[i / 0x200]) == -1) { 2694 if (write_disk(i / 0x200, &bootcode[i / 0x200]) == -1) {
2695 warn("Can't write bootcode"); 2695 warn("Can't write bootcode");
2696 goto protect_label; 2696 goto protect_label;
2697 } 2697 }
2698 for (offset = 0, i = 0; i < ext.num_ptn; i++) { 2698 for (offset = 0, i = 0; i < ext.num_ptn; i++) {
2699 if (write_disk(ext.base + offset, ext.ptn + i) == -1) { 2699 if (write_disk(ext.base + offset, ext.ptn + i) == -1) {
2700 warn("Can't write %dth extended partition", i); 2700 warn("Can't write %dth extended partition", i);
2701 goto protect_label; 2701 goto protect_label;
2702 } 2702 }
2703 offset = le32toh(ext.ptn[i].mbr_parts[1].mbrp_start); 2703 offset = le32toh(ext.ptn[i].mbr_parts[1].mbrp_start);
2704 } 2704 }
2705 rval = 0; 2705 rval = 0;
2706 protect_label: 2706 protect_label:
2707 flag = 0; 2707 flag = 0;
2708 if (wfd == fd && F_flag == 0 && ioctl(wfd, DIOCWLABEL, &flag) < 0) 2708 if (wfd == fd && F_flag == 0 && ioctl(wfd, DIOCWLABEL, &flag) < 0)
2709 warn("DIOCWLABEL"); 2709 warn("DIOCWLABEL");
2710 return rval; 2710 return rval;
2711} 2711}
2712 2712
2713int 2713static int
2714yesno(const char *str, ...) 2714yesno(const char *str, ...)
2715{ 2715{
2716 int ch, first; 2716 int ch, first;
2717 va_list ap; 2717 va_list ap;
2718 2718
2719 va_start(ap, str); 2719 va_start(ap, str);
2720 2720
2721 vprintf(str, ap); 2721 vprintf(str, ap);
2722 printf(" [n] "); 2722 printf(" [n] ");
2723 2723
2724 first = ch = getchar(); 2724 first = ch = getchar();
2725 while (ch != '\n' && ch != EOF) 2725 while (ch != '\n' && ch != EOF)
2726 ch = getchar(); 2726 ch = getchar();
2727 if (ch == EOF) 2727 if (ch == EOF)
2728 errx(1, "EOF"); 2728 errx(1, "EOF");
2729 return (first == 'y' || first == 'Y'); 2729 return (first == 'y' || first == 'Y');
2730} 2730}
2731 2731
2732int64_t 2732static int64_t
2733decimal(const char *prompt, int64_t dflt, int flags, int64_t minval, int64_t maxval) 2733decimal(const char *prompt, int64_t dflt, int flags, int64_t minval, int64_t maxval)
2734{ 2734{
2735 int64_t acc = 0; 2735 int64_t acc = 0;
2736 int valid; 2736 int valid;
2737 int len; 2737 int len;
2738 char *cp; 2738 char *cp;
2739 2739
2740 for (;;) { 2740 for (;;) {
2741 if (flags & DEC_SEC) { 2741 if (flags & DEC_SEC) {
2742 printf("%s: [%" PRId64 "..%" PRId64 "cyl default: %" PRId64 ", %" PRId64 "cyl, %uMB] ", 2742 printf("%s: [%" PRId64 "..%" PRId64 "cyl default: %" PRId64 ", %" PRId64 "cyl, %uMB] ",
2743 prompt, SEC_TO_CYL(minval), SEC_TO_CYL(maxval), 2743 prompt, SEC_TO_CYL(minval), SEC_TO_CYL(maxval),
2744 dflt, SEC_TO_CYL(dflt), SEC_TO_MB(dflt)); 2744 dflt, SEC_TO_CYL(dflt), SEC_TO_MB(dflt));
2745 } else 2745 } else
2746 printf("%s: [%" PRId64 "..%" PRId64 " default: %" PRId64 "] ", 2746 printf("%s: [%" PRId64 "..%" PRId64 " default: %" PRId64 "] ",
2747 prompt, minval, maxval, dflt); 2747 prompt, minval, maxval, dflt);
2748 2748
2749 if (!fgets(lbuf, LBUF, stdin)) 2749 if (!fgets(lbuf, LBUF, stdin))
2750 errx(1, "EOF"); 2750 errx(1, "EOF");
2751 cp = lbuf; 2751 cp = lbuf;
2752 2752
2753 cp += strspn(cp, " \t"); 2753 cp += strspn(cp, " \t");
2754 if (*cp == '\n') 2754 if (*cp == '\n')
2755 return dflt; 2755 return dflt;
2756 2756
2757 if (cp[0] == '$' && cp[1] == '\n') 2757 if (cp[0] == '$' && cp[1] == '\n')
2758 return maxval; 2758 return maxval;
2759 2759
2760 if (isdigit((unsigned char)*cp) || *cp == '-') { 2760 if (isdigit((unsigned char)*cp) || *cp == '-') {
2761 acc = strtoll(lbuf, &cp, 10); 2761 acc = strtoll(lbuf, &cp, 10);
2762 len = strcspn(cp, " \t\n"); 2762 len = strcspn(cp, " \t\n");
2763 valid = 0; 2763 valid = 0;
2764 if (len != 0 && (flags & DEC_SEC)) { 2764 if (len != 0 && (flags & DEC_SEC)) {
2765 if (!strncasecmp(cp, "gb", len)) { 2765 if (!strncasecmp(cp, "gb", len)) {
2766 acc *= 1024; 2766 acc *= 1024;
2767 valid = 1; 2767 valid = 1;
2768 } 2768 }
2769 if (valid || !strncasecmp(cp, "mb", len)) { 2769 if (valid || !strncasecmp(cp, "mb", len)) {
2770 acc *= SEC_IN_1M; 2770 acc *= SEC_IN_1M;
2771 /* round to whole number of cylinders */ 2771 /* round to whole number of cylinders */
2772 acc += ptn_alignment / 2; 2772 acc += ptn_alignment / 2;
2773 acc /= ptn_alignment; 2773 acc /= ptn_alignment;
2774 valid = 1; 2774 valid = 1;
2775 } 2775 }
2776 if (valid || !strncasecmp(cp, "cyl", len)) { 2776 if (valid || !strncasecmp(cp, "cyl", len)) {
2777 acc *= ptn_alignment; 2777 acc *= ptn_alignment;
2778 /* adjustments for cylinder boundary */ 2778 /* adjustments for cylinder boundary */
2779 if (acc == 0 && flags & DEC_RND_0) 2779 if (acc == 0 && flags & DEC_RND_0)
2780 acc += ptn_0_offset; 2780 acc += ptn_0_offset;
2781 if (flags & DEC_RND) 2781 if (flags & DEC_RND)
2782 acc += ptn_0_offset; 2782 acc += ptn_0_offset;
2783 if (flags & DEC_RND_DOWN) 2783 if (flags & DEC_RND_DOWN)
2784 acc -= ptn_0_offset; 2784 acc -= ptn_0_offset;
2785 if (flags & DEC_RND_DOWN_2) 2785 if (flags & DEC_RND_DOWN_2)
2786 acc -= ptn_0_offset; 2786 acc -= ptn_0_offset;
2787 cp += len; 2787 cp += len;
2788 } 2788 }
2789 } 2789 }
2790 } 2790 }
2791 2791
2792 cp += strspn(cp, " \t"); 2792 cp += strspn(cp, " \t");
2793 if (*cp != '\n') { 2793 if (*cp != '\n') {
2794 lbuf[strlen(lbuf) - 1] = 0; 2794 lbuf[strlen(lbuf) - 1] = 0;
2795 printf("%s is not a valid %s number.\n", lbuf, 2795 printf("%s is not a valid %s number.\n", lbuf,
2796 flags & DEC_SEC ? "sector" : "decimal"); 2796 flags & DEC_SEC ? "sector" : "decimal");
2797 continue; 2797 continue;
2798 } 2798 }
2799 2799
2800 if (acc >= minval && acc <= maxval) 2800 if (acc >= minval && acc <= maxval)
2801 return acc; 2801 return acc;
2802 printf("%" PRId64 " is not between %" PRId64 " and %" PRId64 ".\n", acc, minval, maxval); 2802 printf("%" PRId64 " is not between %" PRId64 " and %" PRId64 ".\n", acc, minval, maxval);
2803 } 2803 }
2804} 2804}
2805 2805
2806int 2806static int
2807ptn_id(const char *prompt, int *extended) 2807ptn_id(const char *prompt, int *extended)
2808{ 2808{
2809 unsigned int acc = 0; 2809 unsigned int acc = 0;
2810 char *cp; 2810 char *cp;
2811 2811
2812 for (;; printf("%s is not a valid partition number.\n", lbuf)) { 2812 for (;; printf("%s is not a valid partition number.\n", lbuf)) {
2813 printf("%s: [none] ", prompt); 2813 printf("%s: [none] ", prompt);
2814 2814
2815 if (!fgets(lbuf, LBUF, stdin)) 2815 if (!fgets(lbuf, LBUF, stdin))
2816 errx(1, "EOF"); 2816 errx(1, "EOF");
2817 lbuf[strlen(lbuf)-1] = '\0'; 2817 lbuf[strlen(lbuf)-1] = '\0';
2818 cp = lbuf; 2818 cp = lbuf;
2819 2819
2820 cp += strspn(cp, " \t"); 2820 cp += strspn(cp, " \t");
2821 *extended = 0; 2821 *extended = 0;
2822 if (*cp == 0) 2822 if (*cp == 0)
2823 return -1; 2823 return -1;
2824 2824
2825 if (*cp == 'E' || *cp == 'e') { 2825 if (*cp == 'E' || *cp == 'e') {
2826 cp++; 2826 cp++;
2827 *extended = 1; 2827 *extended = 1;
2828 } 2828 }
2829 2829
2830 acc = strtoul(cp, &cp, 10); 2830 acc = strtoul(cp, &cp, 10);
2831 2831
2832 cp += strspn(cp, " \t"); 2832 cp += strspn(cp, " \t");
2833 if (*cp != '\0') 2833 if (*cp != '\0')
2834 continue; 2834 continue;
2835 2835
2836 if (*extended || acc < MBR_PART_COUNT) 2836 if (*extended || acc < MBR_PART_COUNT)
2837 return acc; 2837 return acc;
2838 } 2838 }
2839} 2839}
2840 2840
2841#ifdef BOOTSEL 2841#ifdef BOOTSEL
2842void 2842static void
2843string(const char *prompt, int length, char *buf) 2843string(const char *prompt, int length, char *buf)
2844{ 2844{
2845 int len; 2845 int len;
2846 2846
2847 for (;;) { 2847 for (;;) {
2848 printf("%s: [%.*s] ", prompt, length, buf); 2848 printf("%s: [%.*s] ", prompt, length, buf);
2849 2849
2850 if (!fgets(lbuf, LBUF, stdin)) 2850 if (!fgets(lbuf, LBUF, stdin))
2851 errx(1, "EOF"); 2851 errx(1, "EOF");
2852 len = strlen(lbuf); 2852 len = strlen(lbuf);
2853 if (len <= 1) 2853 if (len <= 1)
2854 /* unchanged if just <enter> */ 2854 /* unchanged if just <enter> */
2855 return; 2855 return;
2856 /* now strip trailing spaces, <space><enter> deletes string */ 2856 /* now strip trailing spaces, <space><enter> deletes string */
2857 do 2857 do
2858 lbuf[--len] = 0; 2858 lbuf[--len] = 0;
2859 while (len != 0 && lbuf[len - 1] == ' '); 2859 while (len != 0 && lbuf[len - 1] == ' ');
2860 if (len < length) 2860 if (len < length)
2861 break; 2861 break;
2862 printf("'%s' is longer than %d characters.\n", 2862 printf("'%s' is longer than %d characters.\n",
2863 lbuf, length - 1); 2863 lbuf, length - 1);
2864 } 2864 }
2865 strncpy(buf, lbuf, length); 2865 strncpy(buf, lbuf, length);
2866} 2866}
2867#endif 2867#endif
2868 2868
2869int 2869static int
2870type_match(const void *key, const void *item) 2870type_match(const void *key, const void *item)
2871{ 2871{
2872 const int *idp = key; 2872 const int *idp = key;
2873 const struct mbr_ptype *ptr = item; 2873 const struct mbr_ptype *ptr = item;
2874 2874
2875 if (*idp < ptr->id) 2875 if (*idp < ptr->id)
2876 return (-1); 2876 return (-1);
2877 if (*idp > ptr->id) 2877 if (*idp > ptr->id)
2878 return (1); 2878 return (1);
2879 return (0); 2879 return (0);
2880} 2880}
2881 2881
2882const char * 2882static const char *
2883get_type(int type) 2883get_type(int type)
2884{ 2884{
2885 struct mbr_ptype *ptr; 2885 struct mbr_ptype *ptr;
2886 2886
2887 ptr = bsearch(&type, mbr_ptypes, KNOWN_SYSIDS, 2887 ptr = bsearch(&type, mbr_ptypes, KNOWN_SYSIDS,
2888 sizeof(mbr_ptypes[0]), type_match); 2888 sizeof(mbr_ptypes[0]), type_match);
2889 if (ptr == 0) 2889 if (ptr == 0)
2890 return ("unknown"); 2890 return ("unknown");
2891 return (ptr->name); 2891 return (ptr->name);
2892} 2892}
2893 2893
2894int 2894static int
2895read_gpt(daddr_t offset, struct gpt_hdr *gptp) 2895read_gpt(daddr_t offset, struct gpt_hdr *gptp)
2896{ 2896{
2897 char buf[512]; 2897 char buf[512];
2898 struct gpt_hdr *hdr = (void *)buf; 2898 struct gpt_hdr *hdr = (void *)buf;
2899 const char *tabletype = GPT_TYPE(offset); 2899 const char *tabletype = GPT_TYPE(offset);
2900 2900
2901 if (read_disk(offset, buf) == -1) { 2901 if (read_disk(offset, buf) == -1) {
2902 warn("Can't read %s GPT header", tabletype); 2902 warn("Can't read %s GPT header", tabletype);
2903 return -1; 2903 return -1;
2904 } 2904 }
2905 (void)memcpy(gptp, buf, GPT_HDR_SIZE); 2905 (void)memcpy(gptp, buf, GPT_HDR_SIZE);
2906 2906
2907 /* GPT CRC should be calculated with CRC field preset to zero */ 2907 /* GPT CRC should be calculated with CRC field preset to zero */
2908 hdr->hdr_crc_self = 0; 2908 hdr->hdr_crc_self = 0;
2909 2909
2910 if (memcmp(gptp->hdr_sig, GPT_HDR_SIG, sizeof(gptp->hdr_sig)) 2910 if (memcmp(gptp->hdr_sig, GPT_HDR_SIG, sizeof(gptp->hdr_sig))
2911 || gptp->hdr_lba_self != (uint64_t)offset 2911 || gptp->hdr_lba_self != (uint64_t)offset
2912 || crc32(0, (void *)hdr, gptp->hdr_size) != gptp->hdr_crc_self) { 2912 || crc32(0, (void *)hdr, gptp->hdr_size) != gptp->hdr_crc_self) {
2913 /* not a GPT */ 2913 /* not a GPT */
2914 (void)memset(gptp, 0, GPT_HDR_SIZE); 2914 (void)memset(gptp, 0, GPT_HDR_SIZE);
2915 } 2915 }
2916 2916
2917 if (v_flag && gptp->hdr_size != 0) { 2917 if (v_flag && gptp->hdr_size != 0) {
2918 printf("Found %s GPT header CRC %"PRIu32" " 2918 printf("Found %s GPT header CRC %"PRIu32" "
2919 "at sector %"PRIdaddr", backup at %"PRIdaddr"\n", 2919 "at sector %"PRIdaddr", backup at %"PRIdaddr"\n",
2920 tabletype, gptp->hdr_crc_self, offset, gptp->hdr_lba_alt); 2920 tabletype, gptp->hdr_crc_self, offset, gptp->hdr_lba_alt);
2921 } 2921 }
2922 return gptp->hdr_size; 2922 return gptp->hdr_size;
2923 2923
2924} 2924}
2925 2925
2926int 2926static int
2927delete_gpt(struct gpt_hdr *gptp) 2927delete_gpt(struct gpt_hdr *gptp)
2928{ 2928{
2929 char buf[512]; 2929 char buf[512];
2930 struct gpt_hdr *hdr = (void *)buf; 2930 struct gpt_hdr *hdr = (void *)buf;
2931 2931
2932 if (gptp->hdr_size == 0) 2932 if (gptp->hdr_size == 0)
2933 return 0; 2933 return 0;
2934 2934
2935 /* don't accidently overwrite something important */ 2935 /* don't accidently overwrite something important */
2936 if (gptp->hdr_lba_self != GPT_HDR_BLKNO && 2936 if (gptp->hdr_lba_self != GPT_HDR_BLKNO &&
2937 gptp->hdr_lba_self != (uint64_t)disksectors - 1) { 2937 gptp->hdr_lba_self != (uint64_t)disksectors - 1) {
2938 warnx("given GPT header location doesn't seem correct"); 2938 warnx("given GPT header location doesn't seem correct");
2939 return -1; 2939 return -1;
2940 } 2940 }
2941 2941
2942 (void)memcpy(buf, gptp, GPT_HDR_SIZE); 2942 (void)memcpy(buf, gptp, GPT_HDR_SIZE);
2943 /* 2943 /*
2944 * Don't really delete GPT, just "disable" it, so it can 2944 * Don't really delete GPT, just "disable" it, so it can
2945 * be recovered later in case of mistake or something 2945 * be recovered later in case of mistake or something
2946 */ 2946 */
2947 (void)memset(hdr->hdr_sig, 0, sizeof(gptp->hdr_sig)); 2947 (void)memset(hdr->hdr_sig, 0, sizeof(gptp->hdr_sig));
2948 if (write_disk(gptp->hdr_lba_self, hdr) == -1) { 2948 if (write_disk(gptp->hdr_lba_self, hdr) == -1) {
2949 warn("can't delete %s GPT header", 2949 warn("can't delete %s GPT header",
2950 GPT_TYPE(gptp->hdr_lba_self)); 2950 GPT_TYPE(gptp->hdr_lba_self));
2951 return -1; 2951 return -1;
2952 } 2952 }
2953 (void)memset(gptp, 0, GPT_HDR_SIZE); 2953 (void)memset(gptp, 0, GPT_HDR_SIZE);
2954 return 1; 2954 return 1;
2955} 2955}