1*01a159e4Skrw /* $OpenBSD: cmd.c,v 1.180 2024/03/01 17:48:03 krw Exp $ */
2a1705421Sweingart
3a1705421Sweingart /*
4a1705421Sweingart * Copyright (c) 1997 Tobias Weingartner
5a1705421Sweingart *
610a68084Skrw * Permission to use, copy, modify, and distribute this software for any
710a68084Skrw * purpose with or without fee is hereby granted, provided that the above
810a68084Skrw * copyright notice and this permission notice appear in all copies.
9a1705421Sweingart *
1010a68084Skrw * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1110a68084Skrw * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1210a68084Skrw * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1310a68084Skrw * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1410a68084Skrw * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1510a68084Skrw * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1610a68084Skrw * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17a1705421Sweingart */
18a1705421Sweingart
19a7568474Sderaadt #include <sys/types.h>
20a7568474Sderaadt #include <sys/disklabel.h>
21729290c0Skrw
22e8252b55Skrw #include <err.h>
2385135147Skrw #include <errno.h>
24729290c0Skrw #include <signal.h>
25729290c0Skrw #include <stdint.h>
26a1705421Sweingart #include <stdio.h>
27a1705421Sweingart #include <stdlib.h>
28bdf84265Skrw #include <string.h>
29fba7235cSkrw #include <uuid.h>
30abc6f793Skrw
31199eafeaSkrw #include "part.h"
32a5472107Skrw #include "disk.h"
33e8252b55Skrw #include "misc.h"
34a5472107Skrw #include "mbr.h"
35fba7235cSkrw #include "gpt.h"
36a1705421Sweingart #include "user.h"
37a1705421Sweingart #include "cmd.h"
38a1705421Sweingart
39859be6c9Skrw int gedit(const int);
40859be6c9Skrw int edit(const int, struct mbr *);
41859be6c9Skrw int gsetpid(const int);
42859be6c9Skrw int setpid(const int, struct mbr *);
43859be6c9Skrw int parsepn(const char *);
4485135147Skrw int parseflag(const char *, uint64_t *);
45fba7235cSkrw
46543185b3Skrw int ask_num(const char *, int, int, int);
47ede3ff43Skrw int ask_pid(const int);
488c6d22aeSkrw const struct uuid *ask_uuid(const struct uuid *);
49543185b3Skrw
508c10a749Skrw extern const unsigned char manpage[];
518c10a749Skrw extern const int manpage_sz;
528c10a749Skrw
53a1705421Sweingart int
Xreinit(const char * args,struct mbr * mbr)54c5fb5a34Skrw Xreinit(const char *args, struct mbr *mbr)
55a1705421Sweingart {
56c94b0391Skrw int dogpt;
5717eb2d2cSkrw
58c94b0391Skrw dogpt = 0;
59fba7235cSkrw
60380d744dSkrw if (strcasecmp(args, "gpt") == 0)
61fba7235cSkrw dogpt = 1;
62380d744dSkrw else if (strcasecmp(args, "mbr") == 0)
63fba7235cSkrw dogpt = 0;
64fba7235cSkrw else if (strlen(args) > 0) {
65fba7235cSkrw printf("Unrecognized modifier '%s'\n", args);
662a536aa2Skrw return CMD_CONT;
67c94b0391Skrw }
68a1705421Sweingart
69fba7235cSkrw if (dogpt) {
70199eafeaSkrw GPT_init(GHANDGP);
713bbc645fSkrw GPT_print("s", TERSE);
72fba7235cSkrw } else {
73ac519580Skrw MBR_init(mbr);
74fba7235cSkrw MBR_print(mbr, "s");
75fba7235cSkrw }
76e627f006Spefo
77a1705421Sweingart printf("Use 'write' to update disk.\n");
78a1705421Sweingart
792a536aa2Skrw return CMD_DIRTY;
80a1705421Sweingart }
81a1705421Sweingart
82a1705421Sweingart int
Xswap(const char * args,struct mbr * mbr)83c5fb5a34Skrw Xswap(const char *args, struct mbr *mbr)
8498d2b0d2Sderaadt {
85c5fb5a34Skrw char lbuf[LINEBUFSZ];
864f0166f6Skrw char *from, *to;
87996aff7bSkrw int pf, pt;
8853f0474fSkrw struct prt pp;
89fba7235cSkrw struct gpt_partition gg;
9098d2b0d2Sderaadt
91c5fb5a34Skrw if (strlcpy(lbuf, args, sizeof(lbuf)) >= sizeof(lbuf)) {
92c5fb5a34Skrw printf("argument string too long\n");
93c5fb5a34Skrw return CMD_CONT;
94c5fb5a34Skrw }
95c5fb5a34Skrw
96c5fb5a34Skrw to = lbuf;
97380d744dSkrw from = strsep(&to, WHITESPACE);
984f0166f6Skrw
99996aff7bSkrw pt = parsepn(to);
100996aff7bSkrw if (pt == -1)
1012a536aa2Skrw return CMD_CONT;
10298d2b0d2Sderaadt
103996aff7bSkrw pf = parsepn(from);
104996aff7bSkrw if (pf == -1)
1052a536aa2Skrw return CMD_CONT;
10698d2b0d2Sderaadt
10798d2b0d2Sderaadt if (pt == pf) {
10898d2b0d2Sderaadt printf("%d same partition as %d, doing nothing.\n", pt, pf);
1092a536aa2Skrw return CMD_CONT;
11098d2b0d2Sderaadt }
11198d2b0d2Sderaadt
112ad6c5e72Skrw if (gh.gh_sig == GPTSIGNATURE) {
113fba7235cSkrw gg = gp[pt];
114fba7235cSkrw gp[pt] = gp[pf];
115fba7235cSkrw gp[pf] = gg;
116fba7235cSkrw } else {
117061e6e0aSkrw pp = mbr->mbr_prt[pt];
118061e6e0aSkrw mbr->mbr_prt[pt] = mbr->mbr_prt[pf];
119061e6e0aSkrw mbr->mbr_prt[pf] = pp;
120fba7235cSkrw }
12198d2b0d2Sderaadt
1222a536aa2Skrw return CMD_DIRTY;
12398d2b0d2Sderaadt }
12498d2b0d2Sderaadt
12598d2b0d2Sderaadt int
gedit(const int pn)126859be6c9Skrw gedit(const int pn)
127fba7235cSkrw {
128386fe449Skrw struct uuid oldtype;
129fba7235cSkrw
130e4e9ede8Skrw oldtype = gp[pn].gp_type;
131fba7235cSkrw
132386fe449Skrw if (gsetpid(pn))
133386fe449Skrw return -1;
134320e14e3Skrw
135e4e9ede8Skrw if (uuid_is_nil(&gp[pn].gp_type, NULL)) {
136386fe449Skrw if (uuid_is_nil(&oldtype, NULL) == 0) {
137e4e9ede8Skrw memset(&gp[pn], 0, sizeof(gp[pn]));
138fba7235cSkrw printf("Partition %d is disabled.\n", pn);
139386fe449Skrw }
140386fe449Skrw return 0;
141fba7235cSkrw }
142fba7235cSkrw
143c2d03168Skrw if (GPT_get_lba_start(pn) == -1 ||
144a66d82b0Skrw GPT_get_lba_end(pn) == -1 ||
145a66d82b0Skrw GPT_get_name(pn) == -1) {
146386fe449Skrw return -1;
147c2d03168Skrw }
148fba7235cSkrw
149386fe449Skrw return 0;
150fba7235cSkrw }
151fba7235cSkrw
152fba7235cSkrw int
parsepn(const char * pnstr)153859be6c9Skrw parsepn(const char *pnstr)
154996aff7bSkrw {
155996aff7bSkrw const char *errstr;
156996aff7bSkrw int maxpn, pn;
157996aff7bSkrw
158996aff7bSkrw if (pnstr == NULL) {
159996aff7bSkrw printf("no partition number\n");
160996aff7bSkrw return -1;
161996aff7bSkrw }
162996aff7bSkrw
163ad6c5e72Skrw if (gh.gh_sig == GPTSIGNATURE)
164ad6c5e72Skrw maxpn = gh.gh_part_num - 1;
165996aff7bSkrw else
166996aff7bSkrw maxpn = NDOSPART - 1;
167996aff7bSkrw
168996aff7bSkrw pn = strtonum(pnstr, 0, maxpn, &errstr);
169996aff7bSkrw if (errstr) {
170996aff7bSkrw printf("partition number is %s: %s\n", errstr, pnstr);
171996aff7bSkrw return -1;
172996aff7bSkrw }
173996aff7bSkrw
174996aff7bSkrw return pn;
175996aff7bSkrw }
176996aff7bSkrw
177996aff7bSkrw int
parseflag(const char * flagstr,uint64_t * flagvalue)17885135147Skrw parseflag(const char *flagstr, uint64_t *flagvalue)
17985135147Skrw {
18085135147Skrw const char *errstr;
18185135147Skrw char *ep;
18285135147Skrw uint64_t val;
18385135147Skrw
18414c04d21Skrw flagstr += strspn(flagstr, WHITESPACE);
18585135147Skrw if (flagstr[0] == '0' && (flagstr[1] == 'x' || flagstr[1] == 'X')) {
18685135147Skrw errno = 0;
18785135147Skrw val = strtoull(flagstr, &ep, 16);
18885135147Skrw if (errno || ep == flagstr || *ep != '\0' ||
18985135147Skrw (gh.gh_sig != GPTSIGNATURE && val > 0xff)) {
19085135147Skrw printf("flag value is invalid: %s\n", flagstr);
19185135147Skrw return -1;
19285135147Skrw }
19385135147Skrw goto done;
19485135147Skrw }
19585135147Skrw
19685135147Skrw if (gh.gh_sig == GPTSIGNATURE)
19785135147Skrw val = strtonum(flagstr, 0, INT64_MAX, &errstr);
19885135147Skrw else
19985135147Skrw val = strtonum(flagstr, 0, 0xff, &errstr);
20085135147Skrw if (errstr) {
20185135147Skrw printf("flag value is %s: %s\n", errstr, flagstr);
20285135147Skrw return -1;
20385135147Skrw }
20485135147Skrw
20585135147Skrw done:
20685135147Skrw *flagvalue = val;
20785135147Skrw return 0;
20885135147Skrw }
20985135147Skrw
21085135147Skrw int
edit(const int pn,struct mbr * mbr)211859be6c9Skrw edit(const int pn, struct mbr *mbr)
212a1705421Sweingart {
21377392607Skrw struct chs start, end;
21453f0474fSkrw struct prt *pp;
21545d8ccdeSkrw uint64_t track;
216386fe449Skrw unsigned char oldid;
217c2b81596Skrw
218061e6e0aSkrw pp = &mbr->mbr_prt[pn];
219386fe449Skrw oldid = pp->prt_id;
22099b7b375Smickey
221386fe449Skrw if (setpid(pn, mbr))
222386fe449Skrw return -1;
223386fe449Skrw
224ee38fe33Skrw if (pp->prt_id == DOSPTYP_UNUSED) {
225386fe449Skrw if (oldid != DOSPTYP_UNUSED) {
226a1705421Sweingart memset(pp, 0, sizeof(*pp));
227a2f126afSderaadt printf("Partition %d is disabled.\n", pn);
2287f41e46fSkrw }
229386fe449Skrw return 0;
230a1705421Sweingart }
231a1705421Sweingart
232a1705421Sweingart if (ask_yn("Do you wish to edit in CHS mode?")) {
23377392607Skrw PRT_lba_to_chs(pp, &start, &end);
23477392607Skrw start.chs_cyl = ask_num("BIOS Starting cylinder", start.chs_cyl,
235d91eacccSkrw 0, disk.dk_cylinders - 1);
23677392607Skrw start.chs_head = ask_num("BIOS Starting head", start.chs_head,
237d91eacccSkrw 0, disk.dk_heads - 1);
23877392607Skrw start.chs_sect = ask_num("BIOS Starting sector", start.chs_sect,
239d91eacccSkrw 1, disk.dk_sectors);
240a1705421Sweingart
24177392607Skrw end.chs_cyl = ask_num("BIOS Ending cylinder", end.chs_cyl,
24277392607Skrw start.chs_cyl, disk.dk_cylinders - 1);
24377392607Skrw end.chs_head = ask_num("BIOS Ending head", end.chs_head,
24477392607Skrw (start.chs_cyl == end.chs_cyl) ? start.chs_head : 0,
245d91eacccSkrw disk.dk_heads - 1);
24677392607Skrw end.chs_sect = ask_num("BIOS Ending sector", end.chs_sect,
24777392607Skrw (start.chs_cyl == end.chs_cyl && start.chs_head ==
24877392607Skrw end.chs_head) ? start.chs_sect : 1, disk.dk_sectors);
249a1705421Sweingart
25045d8ccdeSkrw /* The ATA/ATAPI spec says LBA = (C × HPC + H) × SPT + (S − 1) */
25177392607Skrw track = start.chs_cyl * disk.dk_heads + start.chs_head;
25277392607Skrw pp->prt_bs = track * disk.dk_sectors + (start.chs_sect - 1);
25377392607Skrw track = end.chs_cyl * disk.dk_heads + end.chs_head;
25477392607Skrw pp->prt_ns = track * disk.dk_sectors + (end.chs_sect - 1) -
25545d8ccdeSkrw pp->prt_bs + 1;
256a1705421Sweingart } else {
257d91eacccSkrw pp->prt_bs = getuint64("Partition offset", pp->prt_bs, 0,
258d91eacccSkrw disk.dk_size - 1);
259ee38fe33Skrw pp->prt_ns = getuint64("Partition size", pp->prt_ns, 1,
26033e90638Skrw disk.dk_size - pp->prt_bs);
261a1705421Sweingart }
2627126966cSkrw
263386fe449Skrw return 0;
264a1705421Sweingart }
265a1705421Sweingart
266a1705421Sweingart int
Xedit(const char * args,struct mbr * mbr)267c5fb5a34Skrw Xedit(const char *args, struct mbr *mbr)
268f05f27a7Skrw {
269386fe449Skrw struct gpt_partition oldgg;
270386fe449Skrw struct prt oldprt;
271f05f27a7Skrw int pn;
272f05f27a7Skrw
273f05f27a7Skrw pn = parsepn(args);
274f05f27a7Skrw if (pn == -1)
2752a536aa2Skrw return CMD_CONT;
276f05f27a7Skrw
277ad6c5e72Skrw if (gh.gh_sig == GPTSIGNATURE) {
278386fe449Skrw oldgg = gp[pn];
279386fe449Skrw if (gedit(pn))
280386fe449Skrw gp[pn] = oldgg;
281e4e9ede8Skrw else if (memcmp(&gp[pn], &oldgg, sizeof(gp[pn])))
282386fe449Skrw return CMD_DIRTY;
283386fe449Skrw } else {
284386fe449Skrw oldprt = mbr->mbr_prt[pn];
285386fe449Skrw if (edit(pn, mbr))
286386fe449Skrw mbr->mbr_prt[pn] = oldprt;
287386fe449Skrw else if (memcmp(&mbr->mbr_prt[pn], &oldprt, sizeof(oldprt)))
288386fe449Skrw return CMD_DIRTY;
289386fe449Skrw }
290386fe449Skrw
291386fe449Skrw return CMD_CONT;
292f05f27a7Skrw }
293f05f27a7Skrw
294f05f27a7Skrw int
gsetpid(const int pn)295a3a83fc4Skrw gsetpid(const int pn)
296fba7235cSkrw {
297*01a159e4Skrw int32_t is_nil;
298351f0068Skrw uint32_t status;
299fba7235cSkrw
3003bbc645fSkrw GPT_print_parthdr(TERSE);
3013bbc645fSkrw GPT_print_part(pn, "s", TERSE);
302fba7235cSkrw
303490259bdSkrw if (PRT_protected_uuid(&gp[pn].gp_type)) {
30495e8765cSkrw printf("can't edit partition type %s\n",
305d8f6db85Skrw PRT_uuid_to_desc(&gp[pn].gp_type));
306386fe449Skrw return -1;
30795e8765cSkrw }
30895e8765cSkrw
309*01a159e4Skrw is_nil = uuid_is_nil(&gp[pn].gp_type, NULL);
3102de77560Skrw gp[pn].gp_type = *ask_uuid(&gp[pn].gp_type);
311*01a159e4Skrw if (PRT_protected_uuid(&gp[pn].gp_type) && is_nil == 0) {
31295e8765cSkrw printf("can't change partition type to %s\n",
313d8f6db85Skrw PRT_uuid_to_desc(&gp[pn].gp_type));
314386fe449Skrw return -1;
31595e8765cSkrw }
316fba7235cSkrw
3172de77560Skrw if (uuid_is_nil(&gp[pn].gp_guid, NULL)) {
3182de77560Skrw uuid_create(&gp[pn].gp_guid, &status);
319fba7235cSkrw if (status != uuid_s_ok) {
320fba7235cSkrw printf("could not create guid for partition\n");
321386fe449Skrw return -1;
322fba7235cSkrw }
323386fe449Skrw }
324386fe449Skrw
325386fe449Skrw return 0;
326fba7235cSkrw }
327fba7235cSkrw
328fba7235cSkrw int
setpid(const int pn,struct mbr * mbr)329a3a83fc4Skrw setpid(const int pn, struct mbr *mbr)
3305c65ba20Sangelos {
33153f0474fSkrw struct prt *pp;
332c2b81596Skrw
333061e6e0aSkrw pp = &mbr->mbr_prt[pn];
3345c65ba20Sangelos
3357b70791fSkrw PRT_print_parthdr();
3367b70791fSkrw PRT_print_part(pn, pp, "s");
3375c65ba20Sangelos
338ede3ff43Skrw pp->prt_id = ask_pid(pp->prt_id);
3395c65ba20Sangelos
340386fe449Skrw return 0;
3415c65ba20Sangelos }
3425675a19dSderaadt
3435c65ba20Sangelos int
Xsetpid(const char * args,struct mbr * mbr)344c5fb5a34Skrw Xsetpid(const char *args, struct mbr *mbr)
345f05f27a7Skrw {
346386fe449Skrw struct gpt_partition oldgg;
347386fe449Skrw struct prt oldprt;
348f05f27a7Skrw int pn;
349f05f27a7Skrw
350f05f27a7Skrw pn = parsepn(args);
351f05f27a7Skrw if (pn == -1)
3522a536aa2Skrw return CMD_CONT;
353f05f27a7Skrw
354ad6c5e72Skrw if (gh.gh_sig == GPTSIGNATURE) {
355386fe449Skrw oldgg = gp[pn];
356386fe449Skrw if (gsetpid(pn))
357386fe449Skrw gp[pn] = oldgg;
358e4e9ede8Skrw else if (memcmp(&gp[pn], &oldgg, sizeof(gp[pn])))
359386fe449Skrw return CMD_DIRTY;
360386fe449Skrw } else {
361386fe449Skrw oldprt = mbr->mbr_prt[pn];
362386fe449Skrw if (setpid(pn, mbr))
363386fe449Skrw mbr->mbr_prt[pn] = oldprt;
364386fe449Skrw else if (memcmp(&mbr->mbr_prt[pn], &oldprt, sizeof(oldprt)))
365386fe449Skrw return CMD_DIRTY;
366386fe449Skrw }
367386fe449Skrw
368386fe449Skrw return CMD_CONT;
369f05f27a7Skrw }
370f05f27a7Skrw
371f05f27a7Skrw int
Xselect(const char * args,struct mbr * mbr)372c5fb5a34Skrw Xselect(const char *args, struct mbr *mbr)
373a1705421Sweingart {
3740cd9e2afSkrw static uint64_t lba_firstembr = 0;
3750cd9e2afSkrw uint64_t lba_self;
37699b7b375Smickey int pn;
377a1705421Sweingart
378996aff7bSkrw pn = parsepn(args);
379996aff7bSkrw if (pn == -1)
3802a536aa2Skrw return CMD_CONT;
381a1705421Sweingart
3820cd9e2afSkrw lba_self = mbr->mbr_prt[pn].prt_bs;
383a1705421Sweingart
384ee38fe33Skrw if ((mbr->mbr_prt[pn].prt_id != DOSPTYP_EXTEND) &&
385ee38fe33Skrw (mbr->mbr_prt[pn].prt_id != DOSPTYP_EXTENDL)) {
38699b7b375Smickey printf("Partition %d is not an extended partition.\n", pn);
3872a536aa2Skrw return CMD_CONT;
388a1705421Sweingart }
389ca2e86e1Sprovos
3900cd9e2afSkrw if (lba_firstembr == 0)
3910cd9e2afSkrw lba_firstembr = lba_self;
392ca2e86e1Sprovos
3930cd9e2afSkrw if (lba_self == 0) {
3940cd9e2afSkrw printf("Loop to MBR (sector 0)! Not selected.\n");
3952a536aa2Skrw return CMD_CONT;
396a1705421Sweingart } else {
39799b7b375Smickey printf("Selected extended partition %d\n", pn);
3980cd9e2afSkrw printf("New EMBR at offset %llu.\n", lba_self);
399a1705421Sweingart }
400a1705421Sweingart
4010cd9e2afSkrw USER_edit(lba_self, lba_firstembr);
4027126966cSkrw
4032a536aa2Skrw return CMD_CONT;
404a1705421Sweingart }
405a1705421Sweingart
406a1705421Sweingart int
Xprint(const char * args,struct mbr * mbr)407c5fb5a34Skrw Xprint(const char *args, struct mbr *mbr)
408a1705421Sweingart {
409ad6c5e72Skrw if (gh.gh_sig == GPTSIGNATURE)
4103bbc645fSkrw GPT_print(args, VERBOSE);
4119ba61043Skrw else if (MBR_valid_prt(mbr))
41287dc5144Skrw MBR_print(mbr, args);
4139ba61043Skrw else {
4149ba61043Skrw DISK_printgeometry("s");
4159ba61043Skrw printf("Offset: %d\tSignature: 0x%X.\tNo MBR or GPT.\n",
4169ba61043Skrw DOSBBSECTOR, (int)mbr->mbr_signature);
4179ba61043Skrw }
418a1705421Sweingart
4192a536aa2Skrw return CMD_CONT;
420a1705421Sweingart }
421a1705421Sweingart
422a1705421Sweingart int
Xwrite(const char * args,struct mbr * mbr)423c5fb5a34Skrw Xwrite(const char *args, struct mbr *mbr)
424a1705421Sweingart {
4255f7fe693Skrw unsigned int i, n;
426f1102820Smatthew
4275f7fe693Skrw for (i = 0, n = 0; i < nitems(mbr->mbr_prt); i++)
42844ce0cacSkrw if (mbr->mbr_prt[i].prt_id == DOSPTYP_OPENBSD)
429f1102820Smatthew n++;
43044ce0cacSkrw if (n > 1) {
431f1102820Smatthew warnx("MBR contains more than one OpenBSD partition!");
43244ce0cacSkrw if (ask_yn("Write MBR anyway?") == 0)
4332a536aa2Skrw return CMD_CONT;
434f1102820Smatthew }
435a1705421Sweingart
436ad6c5e72Skrw if (gh.gh_sig == GPTSIGNATURE) {
437dfcac45eSkrw printf("Writing GPT.\n");
438dfcac45eSkrw if (GPT_write() == -1) {
43945a092d7Skrw warnx("error writing GPT");
440dfcac45eSkrw return CMD_CONT;
441dfcac45eSkrw }
442dfcac45eSkrw } else {
443530f0457Skrw printf("Writing MBR at offset %llu.\n", mbr->mbr_lba_self);
444e79775dbSkrw if (MBR_write(mbr) == -1) {
44545a092d7Skrw warnx("error writing MBR");
4462a536aa2Skrw return CMD_CONT;
4472ab1ffe2Skrw }
448c94b0391Skrw GPT_zap_headers();
449fba7235cSkrw }
4502ab1ffe2Skrw
4512a536aa2Skrw return CMD_CLEAN;
452a1705421Sweingart }
453a1705421Sweingart
454a1705421Sweingart int
Xquit(const char * args,struct mbr * mbr)455c5fb5a34Skrw Xquit(const char *args, struct mbr *mbr)
456a1705421Sweingart {
457711fb9d5Skrw return CMD_QUIT;
458a1705421Sweingart }
459a1705421Sweingart
460a1705421Sweingart int
Xabort(const char * args,struct mbr * mbr)461c5fb5a34Skrw Xabort(const char *args, struct mbr *mbr)
4624b464610Sderaadt {
4634b464610Sderaadt exit(0);
4644b464610Sderaadt }
4654b464610Sderaadt
4664b464610Sderaadt int
Xexit(const char * args,struct mbr * mbr)467c5fb5a34Skrw Xexit(const char *args, struct mbr *mbr)
468a1705421Sweingart {
4692a536aa2Skrw return CMD_EXIT;
470a1705421Sweingart }
471a1705421Sweingart
472a1705421Sweingart int
Xhelp(const char * args,struct mbr * mbr)473c5fb5a34Skrw Xhelp(const char *args, struct mbr *mbr)
474a1705421Sweingart {
4759ba61043Skrw USER_help(mbr);
476fba7235cSkrw
4772a536aa2Skrw return CMD_CONT;
478a1705421Sweingart }
479a1705421Sweingart
480a1705421Sweingart int
Xupdate(const char * args,struct mbr * mbr)481c5fb5a34Skrw Xupdate(const char *args, struct mbr *mbr)
482a1705421Sweingart {
483f43a9f23Skrw memcpy(mbr->mbr_code, default_dmbr.dmbr_boot, sizeof(mbr->mbr_code));
484061e6e0aSkrw mbr->mbr_signature = DOSMBR_SIGNATURE;
485a1705421Sweingart printf("Machine code updated.\n");
4862a536aa2Skrw return CMD_DIRTY;
487a1705421Sweingart }
488a1705421Sweingart
489a1705421Sweingart int
Xflag(const char * args,struct mbr * mbr)490c5fb5a34Skrw Xflag(const char *args, struct mbr *mbr)
491a1705421Sweingart {
492c5fb5a34Skrw char lbuf[LINEBUFSZ];
49399f63382Skrw char *part, *flag;
49485135147Skrw uint64_t val;
4958c10a749Skrw int i, pn;
496a1705421Sweingart
497c5fb5a34Skrw if (strlcpy(lbuf, args, sizeof(lbuf)) >= sizeof(lbuf)) {
498c5fb5a34Skrw printf("argument string too long\n");
499c5fb5a34Skrw return CMD_CONT;
500c5fb5a34Skrw }
501c5fb5a34Skrw
502c5fb5a34Skrw flag = lbuf;
503380d744dSkrw part = strsep(&flag, WHITESPACE);
50499f63382Skrw
50529fb24ffSkrw pn = parsepn(part);
50629fb24ffSkrw if (pn == -1)
5072a536aa2Skrw return CMD_CONT;
508a1705421Sweingart
50999f63382Skrw if (flag != NULL) {
51085135147Skrw if (parseflag(flag, &val) == -1)
5112a536aa2Skrw return CMD_CONT;
512ad6c5e72Skrw if (gh.gh_sig == GPTSIGNATURE)
5132de77560Skrw gp[pn].gp_attrs = val;
514fba7235cSkrw else
515ee38fe33Skrw mbr->mbr_prt[pn].prt_flag = val;
516fba7235cSkrw printf("Partition %d flag value set to 0x%llx.\n", pn, val);
517fba7235cSkrw } else {
518ad6c5e72Skrw if (gh.gh_sig == GPTSIGNATURE) {
519ad6c5e72Skrw for (i = 0; i < gh.gh_part_num; i++) {
520fba7235cSkrw if (i == pn)
52195a0034fSkrw gp[i].gp_attrs = GPTPARTATTR_BOOTABLE;
522fba7235cSkrw else
52354ee4acdSkrw gp[i].gp_attrs &= ~GPTPARTATTR_BOOTABLE;
524fba7235cSkrw }
525fba7235cSkrw } else {
5265f7fe693Skrw for (i = 0; i < nitems(mbr->mbr_prt); i++) {
5279d22187fSderaadt if (i == pn)
528ee38fe33Skrw mbr->mbr_prt[i].prt_flag = DOSACTIVE;
5299d22187fSderaadt else
530ee38fe33Skrw mbr->mbr_prt[i].prt_flag = 0x00;
531a1705421Sweingart }
532fba7235cSkrw }
53399b7b375Smickey printf("Partition %d marked active.\n", pn);
534513623c8Sotto }
5357126966cSkrw
5362a536aa2Skrw return CMD_DIRTY;
537a1705421Sweingart }
538a1705421Sweingart
539a807549cSderaadt int
Xmanual(const char * args,struct mbr * mbr)540c5fb5a34Skrw Xmanual(const char *args, struct mbr *mbr)
541a807549cSderaadt {
5429d22187fSderaadt char *pager = "/usr/bin/less";
543489bd112Spjanzen char *p;
544a807549cSderaadt FILE *f;
5458c10a749Skrw sig_t opipe;
546a807549cSderaadt
54778b4f672Sweingart opipe = signal(SIGPIPE, SIG_IGN);
548489bd112Spjanzen if ((p = getenv("PAGER")) != NULL && (*p != '\0'))
549489bd112Spjanzen pager = p;
55008f8e31fSotto if (asprintf(&p, "gunzip -qc|%s", pager) != -1) {
55108f8e31fSotto f = popen(p, "w");
552a807549cSderaadt if (f) {
553a5472107Skrw fwrite(manpage, manpage_sz, 1, f);
554a807549cSderaadt pclose(f);
555a807549cSderaadt }
55608f8e31fSotto free(p);
55708f8e31fSotto }
558a807549cSderaadt
559a5472107Skrw signal(SIGPIPE, opipe);
5607126966cSkrw
5612a536aa2Skrw return CMD_CONT;
562a807549cSderaadt }
563543185b3Skrw
564543185b3Skrw int
ask_num(const char * str,int dflt,int low,int high)565543185b3Skrw ask_num(const char *str, int dflt, int low, int high)
566543185b3Skrw {
56763400da5Skrw char lbuf[LINEBUFSZ];
568543185b3Skrw const char *errstr;
569543185b3Skrw int num;
570543185b3Skrw
571543185b3Skrw if (dflt < low)
572543185b3Skrw dflt = low;
573543185b3Skrw else if (dflt > high)
574543185b3Skrw dflt = high;
575543185b3Skrw
576543185b3Skrw do {
577543185b3Skrw printf("%s [%d - %d]: [%d] ", str, low, high, dflt);
578380d744dSkrw string_from_line(lbuf, sizeof(lbuf), TRIMMED);
579543185b3Skrw
580543185b3Skrw if (lbuf[0] == '\0') {
581543185b3Skrw num = dflt;
582543185b3Skrw errstr = NULL;
583543185b3Skrw } else {
584543185b3Skrw num = (int)strtonum(lbuf, low, high, &errstr);
585543185b3Skrw if (errstr)
586543185b3Skrw printf("%s is %s: %s.\n", str, errstr, lbuf);
587543185b3Skrw }
588543185b3Skrw } while (errstr);
589543185b3Skrw
590543185b3Skrw return num;
591543185b3Skrw }
592543185b3Skrw
593543185b3Skrw int
ask_pid(const int dflt)594ede3ff43Skrw ask_pid(const int dflt)
595543185b3Skrw {
59663400da5Skrw char lbuf[LINEBUFSZ];
597ede3ff43Skrw int num;
598543185b3Skrw
5997696a120Skrw for (;;) {
6007696a120Skrw printf("Partition id ('0' to disable) [01 - FF]: [%02X] ", dflt);
601543185b3Skrw printf("(? for help) ");
602380d744dSkrw string_from_line(lbuf, sizeof(lbuf), TRIMMED);
603543185b3Skrw
6047696a120Skrw if (strlen(lbuf) == 0)
6057696a120Skrw return dflt;
606380d744dSkrw if (strcmp(lbuf, "?") == 0) {
607a0193349Skrw PRT_print_mbrmenu(lbuf, sizeof(lbuf));
608a0193349Skrw if (strlen(lbuf) == 0)
609543185b3Skrw continue;
610543185b3Skrw }
611543185b3Skrw
6127696a120Skrw num = hex_octet(lbuf);
6137696a120Skrw if (num != -1)
614543185b3Skrw return num;
6157696a120Skrw
6167696a120Skrw printf("'%s' is not a valid partition id.\n", lbuf);
6177696a120Skrw }
618543185b3Skrw }
619543185b3Skrw
6208c6d22aeSkrw const struct uuid *
ask_uuid(const struct uuid * olduuid)621ede3ff43Skrw ask_uuid(const struct uuid *olduuid)
622ede3ff43Skrw {
62363400da5Skrw char lbuf[LINEBUFSZ];
624f3cf20a5Skrw static struct uuid uuid;
625f3cf20a5Skrw const char *guid;
626f3cf20a5Skrw char *dflt;
627351f0068Skrw uint32_t status;
628ede3ff43Skrw
629f3cf20a5Skrw dflt = PRT_uuid_to_menudflt(olduuid);
630f3cf20a5Skrw if (dflt == NULL) {
631717a7d06Skrw if (asprintf(&dflt, "00") == -1) {
632ede3ff43Skrw warn("asprintf()");
633ede3ff43Skrw goto done;
634ede3ff43Skrw }
635f3cf20a5Skrw }
636ede3ff43Skrw
637ede3ff43Skrw for (;;) {
638ede3ff43Skrw printf("Partition id ('0' to disable) [01 - FF, <uuid>]: [%s] ",
639ede3ff43Skrw dflt);
640ede3ff43Skrw printf("(? for help) ");
641ede3ff43Skrw string_from_line(lbuf, sizeof(lbuf), TRIMMED);
642ede3ff43Skrw
643ede3ff43Skrw if (strcmp(lbuf, "?") == 0) {
644a0193349Skrw PRT_print_gptmenu(lbuf, sizeof(lbuf));
645a0193349Skrw if (strlen(lbuf) == 0)
646ede3ff43Skrw continue;
647ede3ff43Skrw } else if (strlen(lbuf) == 0) {
648ede3ff43Skrw uuid = *olduuid;
649ede3ff43Skrw goto done;
650ede3ff43Skrw }
651ede3ff43Skrw
652f3cf20a5Skrw guid = PRT_menuid_to_guid(hex_octet(lbuf));
653f3cf20a5Skrw if (guid == NULL)
654f3cf20a5Skrw guid = lbuf;
655f3cf20a5Skrw
656f3cf20a5Skrw uuid_from_string(guid, &uuid, &status);
657ede3ff43Skrw if (status == uuid_s_ok)
658ede3ff43Skrw goto done;
659ede3ff43Skrw
660ede3ff43Skrw printf("'%s' has no associated UUID\n", lbuf);
661ede3ff43Skrw }
662ede3ff43Skrw
663ede3ff43Skrw done:
664ede3ff43Skrw free(dflt);
665ede3ff43Skrw return &uuid;
666ede3ff43Skrw }
667