Print this page
9250 remove xpv related code from bootadm
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/boot/bootadm/bootadm_upgrade.c
+++ new/usr/src/cmd/boot/bootadm/bootadm_upgrade.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 * Copyright 2017 Toomas Soome <tsoome@me.com>
25 25 */
26 26
27 27 #include <stdio.h>
28 28 #include <errno.h>
29 29 #include <stdlib.h>
30 30 #include <string.h>
31 31 #include <unistd.h>
32 32 #include <sys/types.h>
33 33 #include <sys/stat.h>
34 34 #include <limits.h>
↓ open down ↓ |
34 lines elided |
↑ open up ↑ |
35 35 #include <fcntl.h>
36 36 #include <strings.h>
37 37
38 38 #include <sys/mman.h>
39 39 #include <sys/elf.h>
40 40 #include <sys/multiboot.h>
41 41
42 42 #include "bootadm.h"
43 43
44 44 direct_or_multi_t bam_direct = BAM_DIRECT_NOT_SET;
45 -hv_t bam_is_hv = BAM_HV_UNKNOWN;
46 45 findroot_t bam_is_findroot = BAM_FINDROOT_UNKNOWN;
47 46
48 47 static void
49 48 get_findroot_cap(const char *osroot)
50 49 {
51 50 FILE *fp;
52 51 char path[PATH_MAX];
53 52 char buf[BAM_MAXLINE];
54 53 struct stat sb;
55 54 int dboot;
56 55 int error;
57 56 int ret;
58 57 const char *fcn = "get_findroot_cap()";
59 58
60 59 (void) snprintf(path, sizeof (path), "%s/%s",
61 60 osroot, "boot/grub/capability");
62 61
63 62 if (stat(path, &sb) == -1) {
64 63 bam_is_findroot = BAM_FINDROOT_ABSENT;
65 64 BAM_DPRINTF(("%s: findroot capability absent\n", fcn));
66 65 return;
67 66 }
68 67
69 68 fp = fopen(path, "r");
70 69 error = errno;
71 70 INJECT_ERROR1("GET_CAP_FINDROOT_FOPEN", fp = NULL);
72 71 if (fp == NULL) {
73 72 bam_error(_("failed to open file: %s: %s\n"), path,
74 73 strerror(error));
75 74 return;
76 75 }
77 76
78 77 dboot = 0;
79 78 while (s_fgets(buf, sizeof (buf), fp) != NULL) {
80 79 if (strcmp(buf, "findroot") == 0) {
81 80 BAM_DPRINTF(("%s: findroot capability present\n", fcn));
82 81 bam_is_findroot = BAM_FINDROOT_PRESENT;
83 82 }
84 83 if (strcmp(buf, "dboot") == 0) {
85 84 BAM_DPRINTF(("%s: dboot capability present\n", fcn));
86 85 dboot = 1;
87 86 }
88 87 }
89 88
90 89 assert(dboot);
91 90
92 91 if (bam_is_findroot == BAM_FINDROOT_UNKNOWN) {
93 92 bam_is_findroot = BAM_FINDROOT_ABSENT;
94 93 BAM_DPRINTF(("%s: findroot capability absent\n", fcn));
95 94 }
96 95
97 96 ret = fclose(fp);
98 97 error = errno;
99 98 INJECT_ERROR1("GET_CAP_FINDROOT_FCLOSE", ret = 1);
100 99 if (ret != 0) {
101 100 bam_error(_("failed to close file: %s: %s\n"),
102 101 path, strerror(error));
103 102 }
104 103 }
105 104
106 105 error_t
107 106 get_boot_cap(const char *osroot)
108 107 {
109 108 char fname[PATH_MAX];
110 109 char *image;
111 110 uchar_t *ident;
112 111 uchar_t class;
113 112 int fd;
114 113 int m;
115 114 multiboot_header_t *mbh;
116 115 struct stat sb;
117 116 int error;
118 117 const char *fcn = "get_boot_cap()";
119 118
120 119 if (is_sparc()) {
121 120 /* there is no non dboot sparc new-boot */
122 121 bam_direct = BAM_DIRECT_DBOOT;
123 122 BAM_DPRINTF(("%s: is sparc - always DBOOT\n", fcn));
124 123 return (BAM_SUCCESS);
125 124 }
126 125
127 126 /*
128 127 * The install media can support both 64 and 32 bit boot
129 128 * by using boot archive as ramdisk image. However, to save
130 129 * the memory, the ramdisk may only have either 32 or 64
131 130 * bit kernel files. To avoid error message about missing unix,
132 131 * we should try both variants here and only complain if neither
133 132 * is found. Since the 64-bit systems are more common, we start
134 133 * from amd64.
135 134 */
136 135 class = ELFCLASS64;
137 136 (void) snprintf(fname, PATH_MAX, "%s/%s", osroot,
138 137 "platform/i86pc/kernel/amd64/unix");
139 138 fd = open(fname, O_RDONLY);
140 139 if (fd < 0) {
141 140 class = ELFCLASS32;
142 141 (void) snprintf(fname, PATH_MAX, "%s/%s", osroot,
143 142 "platform/i86pc/kernel/unix");
144 143 fd = open(fname, O_RDONLY);
145 144 }
146 145 error = errno;
147 146 INJECT_ERROR1("GET_CAP_UNIX_OPEN", fd = -1);
148 147 if (fd < 0) {
149 148 bam_error(_("failed to open file: %s: %s\n"), fname,
150 149 strerror(error));
151 150 return (BAM_ERROR);
152 151 }
153 152
154 153 /*
155 154 * Verify that this is a sane unix at least 8192 bytes in length
156 155 */
157 156 if (fstat(fd, &sb) == -1 || sb.st_size < 8192) {
158 157 (void) close(fd);
159 158 bam_error(_("invalid or corrupted binary: %s\n"), fname);
160 159 return (BAM_ERROR);
161 160 }
162 161
163 162 /*
164 163 * mmap the first 8K
165 164 */
166 165 image = mmap(NULL, 8192, PROT_READ, MAP_SHARED, fd, 0);
167 166 error = errno;
168 167 INJECT_ERROR1("GET_CAP_MMAP", image = MAP_FAILED);
169 168 if (image == MAP_FAILED) {
170 169 bam_error(_("failed to mmap file: %s: %s\n"), fname,
171 170 strerror(error));
172 171 return (BAM_ERROR);
173 172 }
174 173
175 174 ident = (uchar_t *)image;
176 175 if (ident[EI_MAG0] != ELFMAG0 || ident[EI_MAG1] != ELFMAG1 ||
177 176 ident[EI_MAG2] != ELFMAG2 || ident[EI_MAG3] != ELFMAG3) {
178 177 bam_error(_("%s is not an ELF file.\n"), fname);
179 178 return (BAM_ERROR);
180 179 }
181 180 if (ident[EI_CLASS] != class) {
182 181 bam_error(_("%s is wrong ELF class 0x%x\n"), fname,
183 182 ident[EI_CLASS]);
184 183 return (BAM_ERROR);
185 184 }
186 185
187 186 /*
188 187 * The GRUB multiboot header must be 32-bit aligned and completely
189 188 * contained in the 1st 8K of the file. If the unix binary has
190 189 * a multiboot header, then it is a 'dboot' kernel. Otherwise,
191 190 * this kernel must be booted via multiboot -- we call this a
192 191 * 'multiboot' kernel.
193 192 */
194 193 bam_direct = BAM_DIRECT_MULTIBOOT;
195 194 for (m = 0; m < 8192 - sizeof (multiboot_header_t); m += 4) {
196 195 mbh = (void *)(image + m);
↓ open down ↓ |
141 lines elided |
↑ open up ↑ |
197 196 if (mbh->magic == MB_HEADER_MAGIC) {
198 197 BAM_DPRINTF(("%s: is DBOOT unix\n", fcn));
199 198 bam_direct = BAM_DIRECT_DBOOT;
200 199 break;
201 200 }
202 201 }
203 202 (void) munmap(image, 8192);
204 203 (void) close(fd);
205 204
206 205 INJECT_ERROR1("GET_CAP_MULTIBOOT", bam_direct = BAM_DIRECT_MULTIBOOT);
207 - if (bam_direct == BAM_DIRECT_DBOOT) {
208 - if (bam_is_hv == BAM_HV_PRESENT) {
209 - BAM_DPRINTF(("%s: is xVM system\n", fcn));
210 - } else {
211 - BAM_DPRINTF(("%s: is *NOT* xVM system\n", fcn));
212 - }
213 - } else {
206 + if (bam_direct != BAM_DIRECT_DBOOT) {
214 207 BAM_DPRINTF(("%s: is MULTIBOOT unix\n", fcn));
215 208 }
216 209
217 210 /* Not a fatal error if this fails */
218 211 get_findroot_cap(osroot);
219 212
220 213 BAM_DPRINTF(("%s: returning SUCCESS\n", fcn));
221 214 return (BAM_SUCCESS);
222 215 }
223 216
224 217 #define INST_RELEASE "var/sadm/system/admin/INST_RELEASE"
225 218
226 219 /*
227 220 * Return true if root has been bfu'ed. bfu will blow away
228 221 * var/sadm/system/admin/INST_RELEASE, so if it's still there, we can
229 222 * assume the system has not been bfu'ed.
230 223 */
231 224 static int
232 225 is_bfu_system(const char *root)
233 226 {
234 227 static int is_bfu = -1;
235 228 char path[PATH_MAX];
236 229 struct stat sb;
237 230 const char *fcn = "is_bfu_system()";
238 231
239 232 if (is_bfu != -1) {
240 233 BAM_DPRINTF(("%s: already done bfu test. bfu is %s present\n",
241 234 fcn, is_bfu ? "" : "NOT"));
242 235 return (is_bfu);
243 236 }
244 237
245 238 (void) snprintf(path, sizeof (path), "%s/%s", root, INST_RELEASE);
246 239 if (stat(path, &sb) != 0) {
247 240 is_bfu = 1;
248 241 BAM_DPRINTF(("%s: returning SUCCESS\n", fcn));
249 242 } else {
250 243 is_bfu = 0;
251 244 BAM_DPRINTF(("%s: returning FAILURE\n", fcn));
252 245 }
253 246 return (is_bfu);
254 247 }
255 248
256 249 #define MENU_URL(root) (is_bfu_system(root) ? \
257 250 "http://illumos.org/msg/SUNOS-8000-CF" : \
258 251 "http://illumos.org/msg/SUNOS-8000-AK")
259 252
260 253 /*
261 254 * Simply allocate a new line and copy in cmd + sep + arg
262 255 */
263 256 void
264 257 update_line(line_t *linep)
265 258 {
266 259 size_t size;
267 260 const char *fcn = "update_line()";
268 261
269 262 BAM_DPRINTF(("%s: line before update: %s\n", fcn, linep->line));
270 263 free(linep->line);
271 264 size = strlen(linep->cmd) + strlen(linep->sep) + strlen(linep->arg) + 1;
272 265 linep->line = s_calloc(1, size);
273 266 (void) snprintf(linep->line, size, "%s%s%s", linep->cmd, linep->sep,
274 267 linep->arg);
275 268 BAM_DPRINTF(("%s: line after update: %s\n", fcn, linep->line));
276 269 }
277 270
278 271 static char *
279 272 skip_wspace(char *ptr)
280 273 {
281 274 const char *fcn = "skip_wspace()";
282 275
283 276 INJECT_ERROR1("SKIP_WSPACE", ptr = NULL);
284 277 if (ptr == NULL) {
285 278 BAM_DPRINTF(("%s: NULL ptr\n", fcn));
286 279 return (NULL);
287 280 }
288 281
289 282 BAM_DPRINTF(("%s: ptr on entry: %s\n", fcn, ptr));
290 283 for (; *ptr != '\0'; ptr++) {
291 284 if ((*ptr != ' ') && (*ptr != '\t') &&
292 285 (*ptr != '\n'))
293 286 break;
294 287 }
295 288
296 289 ptr = (*ptr == '\0' ? NULL : ptr);
297 290
298 291 BAM_DPRINTF(("%s: ptr on exit: %s\n", fcn, ptr ? ptr : "NULL"));
299 292
300 293 return (ptr);
301 294 }
302 295
303 296 static char *
304 297 rskip_bspace(char *bound, char *ptr)
305 298 {
306 299 const char *fcn = "rskip_bspace()";
307 300 assert(bound);
308 301 assert(ptr);
309 302 assert(bound <= ptr);
310 303 assert(*bound != ' ' && *bound != '\t' && *bound != '\n');
311 304
312 305 BAM_DPRINTF(("%s: ptr on entry: %s\n", fcn, ptr));
313 306 for (; ptr > bound; ptr--) {
314 307 if (*ptr == ' ' || *ptr == '\t' || *ptr == '\n')
315 308 break;
316 309 }
317 310
318 311 BAM_DPRINTF(("%s: ptr on exit: %s\n", fcn, ptr));
319 312 return (ptr);
320 313 }
321 314
322 315 /*
323 316 * The parse_kernel_line function examines a menu.lst kernel line. For
324 317 * multiboot, this is:
325 318 *
326 319 * kernel <multiboot path> <flags1> <kernel path> <flags2>
327 320 *
328 321 * <multiboot path> is either /platform/i86pc/multiboot or /boot/multiboot
329 322 *
330 323 * <kernel path> may be missing, or may be any full or relative path to unix.
331 324 * We check for it by looking for a word ending in "/unix". If it ends
332 325 * in "kernel/unix", we upgrade it to a 32-bit entry. If it ends in
333 326 * "kernel/amd64/unix", we upgrade it to the default entry. Otherwise,
334 327 * it's a custom kernel, and we skip it.
335 328 *
336 329 * <flags*> are anything that doesn't fit either of the above - these will be
337 330 * copied over.
338 331 *
339 332 * For direct boot, the defaults are
340 333 *
341 334 * kernel$ <kernel path> <flags>
342 335 *
343 336 * <kernel path> is one of:
344 337 * /platform/i86pc/kernel/$ISADIR/unix
345 338 * /boot/platform/i86pc/kernel/$ISADIR/unix
346 339 * /platform/i86pc/kernel/unix
347 340 * /platform/i86pc/kernel/amd64/unix
348 341 * /boot/platform/i86pc/kernel/unix
349 342 * /boot/platform/i86pc/kernel/amd64/unix
350 343 *
351 344 * If <kernel path> is any of the last four, the command may also be "kernel".
352 345 *
353 346 * <flags> is anything that isn't <kernel path>.
354 347 *
355 348 * This function is only called to convert a multiboot entry to a dboot entry
356 349 *
357 350 * For safety, we do one more check: if the kernel path starts with /boot,
358 351 * we verify that the new kernel exists before changing it. This is mainly
359 352 * done for bfu, as it may cause the failsafe archives to be a different
360 353 * boot architecture from the newly bfu'ed system.
361 354 */
362 355 static error_t
363 356 cvt_kernel_line(line_t *line, const char *osroot, entry_t *entry)
364 357 {
365 358 char path[PATH_MAX], path_64[PATH_MAX];
366 359 char linebuf[PATH_MAX];
367 360 char new_arg[PATH_MAX];
368 361 struct stat sb, sb_64;
369 362 char *old_ptr;
370 363 char *unix_ptr;
371 364 char *flags1_ptr;
372 365 char *flags2_ptr;
373 366 const char *fcn = "cvt_kernel_line()";
374 367
375 368 BAM_DPRINTF(("%s: entered. args: %s %s\n", fcn, line->line, osroot));
376 369
377 370 /*
378 371 * We only convert multiboot to dboot and nothing else.
379 372 */
380 373 if (!(entry->flags & BAM_ENTRY_MULTIBOOT)) {
381 374 BAM_DPRINTF(("%s: not MULTIBOOT, not converting\n", fcn));
382 375 return (BAM_SUCCESS);
383 376 }
384 377
385 378 if (entry->flags & BAM_ENTRY_FAILSAFE) {
386 379 /*
387 380 * We're attempting to change failsafe to dboot.
388 381 * In the bfu case, we may not have a dboot failsafe
389 382 * kernel i.e. a "unix" under the "/boot" hierarchy.
390 383 * If so, just emit a message in verbose mode and
391 384 * return success.
392 385 */
393 386 BAM_DPRINTF(("%s: trying to convert failsafe to DBOOT\n", fcn));
394 387 (void) snprintf(path, PATH_MAX, "%s%s", osroot,
395 388 DIRECT_BOOT_FAILSAFE_32);
396 389 (void) snprintf(path_64, PATH_MAX, "%s%s", osroot,
397 390 DIRECT_BOOT_FAILSAFE_64);
398 391 if (stat(path, &sb) != 0 && stat(path_64, &sb_64) != 0) {
399 392 if (bam_verbose) {
400 393 bam_error(_("bootadm -m upgrade run, but the "
401 394 "failsafe archives have not been\nupdated. "
402 395 "Not updating line %d\n"), line->lineNum);
403 396 }
404 397 BAM_DPRINTF(("%s: no FAILSAFE unix, not converting\n",
405 398 fcn));
406 399 return (BAM_SUCCESS);
407 400 }
408 401 }
409 402
410 403 /*
411 404 * Make sure we have the correct cmd
412 405 */
413 406
414 407 free(line->cmd);
415 408 line->cmd = s_strdup(menu_cmds[KERNEL_DOLLAR_CMD]);
416 409 BAM_DPRINTF(("%s: converted kernel cmd to %s\n", fcn, line->cmd));
417 410
418 411 assert(sizeof (linebuf) > strlen(line->arg) + 32);
419 412 (void) strlcpy(linebuf, line->arg, sizeof (linebuf));
420 413
421 414 old_ptr = strpbrk(linebuf, " \t\n");
422 415 old_ptr = skip_wspace(old_ptr);
423 416 if (old_ptr == NULL) {
424 417 /*
425 418 * only multiboot and nothing else
426 419 * i.e. flags1 = unix = flags2 = NULL
427 420 */
428 421 flags1_ptr = unix_ptr = flags2_ptr = NULL;
429 422 BAM_DPRINTF(("%s: NULL flags1, unix, flags2\n", fcn))
430 423 goto create;
431 424 }
432 425
433 426 /*
434 427 *
435 428 * old_ptr is either at "flags1" or "unix"
436 429 */
437 430 if ((unix_ptr = strstr(old_ptr, "/unix")) != NULL) {
438 431
439 432 /*
440 433 * There is a unix.
441 434 */
442 435 BAM_DPRINTF(("%s: unix present\n", fcn));
443 436
444 437 /* See if there's a flags2 past unix */
445 438 flags2_ptr = unix_ptr + strlen("/unix");
446 439 flags2_ptr = skip_wspace(flags2_ptr);
447 440 if (flags2_ptr) {
448 441 BAM_DPRINTF(("%s: flags2 present: %s\n", fcn,
449 442 flags2_ptr));
450 443 } else {
451 444 BAM_DPRINTF(("%s: flags2 absent\n", fcn));
452 445 }
453 446
454 447 /* see if there is a flags1 before unix */
455 448 unix_ptr = rskip_bspace(old_ptr, unix_ptr);
456 449
457 450 if (unix_ptr == old_ptr) {
458 451 flags1_ptr = NULL;
459 452 BAM_DPRINTF(("%s: flags1 absent\n", fcn));
460 453 } else {
461 454 flags1_ptr = old_ptr;
462 455 *unix_ptr = '\0';
463 456 unix_ptr++;
464 457 BAM_DPRINTF(("%s: flags1 present: %s\n", fcn,
465 458 flags1_ptr));
466 459 }
467 460
468 461 } else {
469 462 /* There is no unix, there is only a bunch of flags */
470 463 flags1_ptr = old_ptr;
471 464 unix_ptr = flags2_ptr = NULL;
472 465 BAM_DPRINTF(("%s: flags1 present: %s, unix, flags2 absent\n",
473 466 fcn, flags1_ptr));
474 467 }
475 468
476 469 /*
477 470 * With dboot, unix is fixed and is at the beginning. We need to
478 471 * migrate flags1 and flags2
479 472 */
480 473 create:
481 474 if (entry->flags & BAM_ENTRY_FAILSAFE) {
482 475 (void) snprintf(new_arg, sizeof (new_arg), "%s",
483 476 DIRECT_BOOT_FAILSAFE_KERNEL);
484 477 } else {
485 478 (void) snprintf(new_arg, sizeof (new_arg), "%s",
486 479 DIRECT_BOOT_KERNEL);
487 480 }
488 481 BAM_DPRINTF(("%s: converted unix: %s\n", fcn, new_arg));
489 482
490 483 if (flags1_ptr != NULL) {
491 484 (void) strlcat(new_arg, " ", sizeof (new_arg));
492 485 (void) strlcat(new_arg, flags1_ptr, sizeof (new_arg));
493 486 }
494 487
495 488 if (flags2_ptr != NULL) {
496 489 (void) strlcat(new_arg, " ", sizeof (new_arg));
497 490 (void) strlcat(new_arg, flags2_ptr, sizeof (new_arg));
498 491 }
499 492
500 493 BAM_DPRINTF(("%s: converted unix with flags : %s\n", fcn, new_arg));
501 494
502 495 free(line->arg);
503 496 line->arg = s_strdup(new_arg);
504 497 update_line(line);
505 498 BAM_DPRINTF(("%s: converted line is: %s\n", fcn, line->line));
506 499 return (BAM_SUCCESS);
507 500 }
508 501
509 502 /*
510 503 * Similar to above, except this time we're looking at a module line,
511 504 * which is quite a bit simpler.
512 505 *
513 506 * Under multiboot, the archive line is:
514 507 *
515 508 * module /platform/i86pc/boot_archive
516 509 *
517 510 * Under directboot, the archive line is:
518 511 *
519 512 * module$ /platform/i86pc/$ISADIR/boot_archive
520 513 *
521 514 * which may be specified exactly as either of:
522 515 *
523 516 * module /platform/i86pc/boot_archive
524 517 * module /platform/i86pc/amd64/boot_archive
525 518 *
526 519 * Under multiboot, the failsafe is:
527 520 *
528 521 * module /boot/x86.miniroot-safe
529 522 *
530 523 * Under dboot, the failsafe is:
531 524 *
532 525 * module$ /boot/$ISADIR/x86.miniroot-safe
533 526 *
534 527 * which may be specified exactly as either of:
535 528 *
536 529 * module /boot/x86.miniroot-safe
537 530 * module /boot/amd64/x86.miniroot-safe
538 531 */
539 532 static error_t
540 533 cvt_module_line(line_t *line, entry_t *entry)
541 534 {
542 535 const char *fcn = "cvt_module_line()";
543 536
544 537 BAM_DPRINTF(("%s: entered. arg: %s\n", fcn, line->line));
545 538
546 539 /*
547 540 * We only convert multiboot to dboot and nothing else
548 541 */
549 542 if (!(entry->flags & BAM_ENTRY_MULTIBOOT)) {
550 543 BAM_DPRINTF(("%s: not MULTIBOOT, not converting\n", fcn));
551 544 return (BAM_SUCCESS);
552 545 }
553 546
554 547 if (entry->flags & BAM_ENTRY_FAILSAFE) {
555 548 if (strcmp(line->arg, FAILSAFE_ARCHIVE) == 0) {
556 549 BAM_DPRINTF(("%s: failsafe module line needs no "
557 550 "conversion: %s\n", fcn, line->arg));
558 551 BAM_DPRINTF(("%s: returning SUCCESS\n", fcn));
559 552 return (BAM_SUCCESS);
560 553 }
561 554 } else if (strcmp(line->arg, MULTIBOOT_ARCHIVE) != 0) {
562 555 bam_error(_("module command on line %d not recognized.\n"),
563 556 line->lineNum);
564 557 BAM_DPRINTF(("%s: returning FAILURE\n", fcn));
565 558 return (BAM_MSG);
566 559 }
567 560
568 561 free(line->cmd);
569 562 free(line->arg);
570 563 line->cmd = s_strdup(menu_cmds[MODULE_DOLLAR_CMD]);
571 564
572 565 line->arg = s_strdup(entry->flags & BAM_ENTRY_FAILSAFE ?
573 566 FAILSAFE_ARCHIVE : DIRECT_BOOT_ARCHIVE);
574 567
575 568 update_line(line);
576 569 BAM_DPRINTF(("%s: converted module line is: %s\n", fcn, line->line));
577 570 BAM_DPRINTF(("%s: returning SUCCESS\n", fcn));
578 571 return (BAM_SUCCESS);
579 572 }
580 573
581 574 static void
582 575 bam_warn_hand_entries(menu_t *mp, char *osroot)
583 576 {
584 577 int hand_num;
585 578 int hand_max;
586 579 int *hand_list;
587 580 int i;
588 581 entry_t *entry;
589 582 const char *fcn = "bam_warn_hand_entries()";
590 583
591 584 if (bam_force) {
592 585 /*
593 586 * No warning needed, we are automatically converting
594 587 * the "hand" entries
595 588 */
596 589 BAM_DPRINTF(("%s: force specified, no warnings about hand "
597 590 "entries\n", fcn));
598 591 return;
599 592 }
600 593
601 594 hand_num = 0;
602 595 hand_max = BAM_ENTRY_NUM;
603 596 hand_list = s_calloc(1, hand_max);
604 597
605 598 for (entry = mp->entries; entry; entry = entry->next) {
606 599 if (entry->flags & (BAM_ENTRY_BOOTADM|BAM_ENTRY_LU))
607 600 continue;
608 601 BAM_DPRINTF(("%s: found hand entry #: %d\n", fcn,
609 602 entry->entryNum));
610 603 if (++hand_num > hand_max) {
611 604 hand_max *= 2;
612 605 hand_list = s_realloc(hand_list,
613 606 hand_max * sizeof (int));
614 607 }
615 608 hand_list[hand_num - 1] = entry->entryNum;
616 609 }
617 610
618 611 bam_error(_("bootadm(1M) will only upgrade GRUB menu entries added "
619 612 "by \nbootadm(1M) or lu(1M). The following entries on %s will "
620 613 "not be upgraded.\nFor details on manually updating entries, "
621 614 "see %s\n"), osroot, MENU_URL(osroot));
622 615 bam_print_stderr("Entry Number%s: ", (hand_num > 1) ?
623 616 "s" : "");
624 617 for (i = 0; i < hand_num; i++) {
625 618 bam_print_stderr("%d ", hand_list[i]);
626 619 }
627 620 bam_print_stderr("\n");
628 621 }
629 622
630 623 static entry_t *
631 624 find_matching_entry(
632 625 entry_t *estart,
633 626 char *grubsign,
634 627 char *grubroot,
635 628 int root_opt)
636 629 {
637 630 entry_t *entry;
638 631 line_t *line;
639 632 char opt[10];
640 633 const char *fcn = "find_matching_entry()";
641 634
642 635 assert(grubsign);
643 636 assert(root_opt == 0 || root_opt == 1);
644 637
645 638 (void) snprintf(opt, sizeof (opt), "%d", root_opt);
646 639 BAM_DPRINTF(("%s: entered. args: %s %s %s\n", fcn, grubsign,
647 640 grubroot, opt));
648 641
649 642 for (entry = estart; entry; entry = entry->next) {
650 643
651 644 if (!(entry->flags & (BAM_ENTRY_BOOTADM|BAM_ENTRY_LU)) &&
652 645 !bam_force) {
653 646 BAM_DPRINTF(("%s: skipping hand entry #: %d\n",
654 647 fcn, entry->entryNum));
655 648 continue;
656 649 }
657 650
658 651 if (entry->flags & BAM_ENTRY_ROOT) {
659 652 for (line = entry->start; line; line = line->next) {
660 653 if (line->cmd == NULL || line->arg == NULL) {
661 654 if (line == entry->end) {
662 655 BAM_DPRINTF(("%s: entry has "
663 656 "ended\n", fcn));
664 657 break;
665 658 } else {
666 659 BAM_DPRINTF(("%s: skipping "
667 660 "NULL line\n", fcn));
668 661 continue;
669 662 }
670 663 }
671 664 if (strcmp(line->cmd, menu_cmds[ROOT_CMD])
672 665 == 0 && strcmp(line->arg, grubroot) == 0) {
673 666 BAM_DPRINTF(("%s: found matching root "
674 667 "line: %s,%s\n", fcn,
675 668 line->line, grubsign));
676 669 return (entry);
677 670 }
678 671 if (line == entry->end) {
679 672 BAM_DPRINTF(("%s: entry has ended\n",
680 673 fcn));
681 674 break;
682 675 }
683 676 }
684 677 } else if (entry->flags & BAM_ENTRY_FINDROOT) {
685 678 for (line = entry->start; line; line = line->next) {
686 679 if (line->cmd == NULL || line->arg == NULL) {
687 680 if (line == entry->end) {
688 681 BAM_DPRINTF(("%s: entry has "
689 682 "ended\n", fcn));
690 683 break;
691 684 } else {
692 685 BAM_DPRINTF(("%s: skipping "
693 686 "NULL line\n", fcn));
694 687 continue;
695 688 }
696 689 }
697 690 if (strcmp(line->cmd, menu_cmds[FINDROOT_CMD])
698 691 == 0 && strcmp(line->arg, grubsign) == 0) {
699 692 BAM_DPRINTF(("%s: found matching "
700 693 "findroot line: %s,%s\n", fcn,
701 694 line->line, grubsign));
702 695 return (entry);
703 696 }
704 697 if (line == entry->end) {
705 698 BAM_DPRINTF(("%s: entry has ended\n",
706 699 fcn));
707 700 break;
708 701 }
709 702 }
710 703 } else if (root_opt) {
711 704 /* Neither root nor findroot */
712 705 BAM_DPRINTF(("%s: no root or findroot and root is "
713 706 "opt: %d\n", fcn, entry->entryNum));
714 707 return (entry);
715 708 }
716 709 }
717 710
718 711 BAM_DPRINTF(("%s: no matching entry found\n", fcn));
719 712 return (NULL);
720 713 }
721 714
722 715 /*
723 716 * The following is a set of routines that attempt to convert the
724 717 * menu entries for the supplied osroot into a format compatible
725 718 * with the GRUB installation on osroot.
726 719 *
727 720 * Each of these conversion routines make no assumptions about
728 721 * the current state of the menu entry, it does its best to
729 722 * convert the menu entry to the new state. In the process
730 723 * we may either upgrade or downgrade.
731 724 *
732 725 * We don't make any heroic efforts at conversion. It is better
733 726 * to be conservative and bail out at the first sign of error. We will
734 727 * in such cases, point the user at the knowledge-base article
735 728 * so that they can upgrade manually.
736 729 */
737 730 static error_t
738 731 bam_add_findroot(menu_t *mp, char *grubsign, char *grubroot, int root_opt)
739 732 {
740 733 entry_t *entry;
741 734 line_t *line;
742 735 line_t *newlp;
743 736 int update_num;
744 737 char linebuf[PATH_MAX];
745 738 const char *fcn = "bam_add_findroot()";
746 739
747 740 update_num = 0;
748 741
749 742 bam_print(_("converting entries to findroot...\n"));
750 743
751 744 entry = find_matching_entry(mp->entries, grubsign, grubroot, root_opt);
752 745 while (entry != NULL) {
753 746 if (entry->flags & BAM_ENTRY_FINDROOT) {
754 747 /* already converted */
755 748 BAM_DPRINTF(("%s: entry %d already converted to "
756 749 "findroot\n", fcn, entry->entryNum));
757 750 entry = find_matching_entry(entry->next, grubsign,
758 751 grubroot, root_opt);
759 752 continue;
760 753 }
761 754 for (line = entry->start; line; line = line->next) {
762 755 if (line->cmd == NULL || line->arg == NULL) {
763 756 if (line == entry->end) {
764 757 BAM_DPRINTF(("%s: entry has ended\n",
765 758 fcn));
766 759 break;
767 760 } else {
768 761 BAM_DPRINTF(("%s: skipping NULL line\n",
769 762 fcn));
770 763 continue;
771 764 }
772 765 }
773 766 if (strcmp(line->cmd, menu_cmds[TITLE_CMD]) == 0) {
774 767 newlp = s_calloc(1, sizeof (line_t));
775 768 newlp->cmd = s_strdup(menu_cmds[FINDROOT_CMD]);
776 769 newlp->sep = s_strdup(" ");
777 770 newlp->arg = s_strdup(grubsign);
778 771 (void) snprintf(linebuf, sizeof (linebuf),
779 772 "%s%s%s", newlp->cmd, newlp->sep,
780 773 newlp->arg);
781 774 newlp->line = s_strdup(linebuf);
782 775 bam_add_line(mp, entry, line, newlp);
783 776 update_num = 1;
784 777 entry->flags &= ~BAM_ENTRY_ROOT;
785 778 entry->flags |= BAM_ENTRY_FINDROOT;
786 779 BAM_DPRINTF(("%s: added findroot line: %s\n",
787 780 fcn, newlp->line));
788 781 line = newlp;
789 782 }
790 783 if (strcmp(line->cmd, menu_cmds[ROOT_CMD]) == 0) {
791 784 BAM_DPRINTF(("%s: freeing root line: %s\n",
792 785 fcn, line->line));
793 786 unlink_line(mp, line);
794 787 line_free(line);
795 788 }
796 789 if (line == entry->end) {
797 790 BAM_DPRINTF(("%s: entry has ended\n", fcn));
798 791 break;
799 792 }
800 793 }
801 794 entry = find_matching_entry(entry->next, grubsign, grubroot,
802 795 root_opt);
803 796 }
804 797
↓ open down ↓ |
581 lines elided |
↑ open up ↑ |
805 798 if (update_num) {
806 799 BAM_DPRINTF(("%s: updated numbering\n", fcn));
807 800 update_numbering(mp);
808 801 }
809 802
810 803 BAM_DPRINTF(("%s: returning SUCCESS\n", fcn));
811 804 return (BAM_SUCCESS);
812 805 }
813 806
814 807 static error_t
815 -bam_add_hv(menu_t *mp, char *grubsign, char *grubroot, int root_opt)
816 -{
817 - entry_t *entry;
818 - const char *fcn = "bam_add_hv()";
819 -
820 - bam_print(_("adding xVM entries...\n"));
821 -
822 - entry = find_matching_entry(mp->entries, grubsign, grubroot, root_opt);
823 - while (entry != NULL) {
824 - if (entry->flags & BAM_ENTRY_HV) {
825 - BAM_DPRINTF(("%s: entry %d already converted to "
826 - "xvm HV\n", fcn, entry->entryNum));
827 - return (BAM_SUCCESS);
828 - }
829 - entry = find_matching_entry(entry->next, grubsign, grubroot,
830 - root_opt);
831 - }
832 -
833 - (void) add_boot_entry(mp, NEW_HV_ENTRY, grubsign, XEN_MENU,
834 - XEN_KERNEL_MODULE_LINE, DIRECT_BOOT_ARCHIVE, NULL);
835 -
836 - BAM_DPRINTF(("%s: added xVM HV entry via add_boot_entry()\n", fcn));
837 -
838 - update_numbering(mp);
839 -
840 - BAM_DPRINTF(("%s: returning SUCCESS\n", fcn));
841 -
842 - return (BAM_SUCCESS);
843 -}
844 -
845 -static error_t
846 808 bam_add_dboot(
847 809 menu_t *mp,
848 810 char *osroot,
849 811 char *grubsign,
850 812 char *grubroot,
851 813 int root_opt)
852 814 {
853 815 int msg = 0;
854 816 entry_t *entry;
855 817 line_t *line;
856 818 error_t ret;
857 819 const char *fcn = "bam_add_dboot()";
858 820
859 821 bam_print(_("converting entries to dboot...\n"));
860 822
861 823 entry = find_matching_entry(mp->entries, grubsign, grubroot, root_opt);
862 824 while (entry != NULL) {
863 825 for (line = entry->start; line; line = line->next) {
864 826 if (line->cmd == NULL || line->arg == NULL) {
865 827 if (line == entry->end) {
866 828 BAM_DPRINTF(("%s: entry has ended\n",
867 829 fcn));
868 830 break;
869 831 } else {
870 832 BAM_DPRINTF(("%s: skipping NULL line\n",
871 833 fcn));
872 834 continue;
873 835 }
874 836 }
875 837
876 838 /*
877 839 * If we have a kernel$ command, assume it
878 840 * is dboot already. If it is not a dboot
879 841 * entry, something funny is going on and
880 842 * we will leave it alone
881 843 */
882 844 if (strcmp(line->cmd, menu_cmds[KERNEL_CMD]) == 0) {
883 845 ret = cvt_kernel_line(line, osroot, entry);
884 846 INJECT_ERROR1("ADD_DBOOT_KERN_ERR",
885 847 ret = BAM_ERROR);
886 848 INJECT_ERROR1("ADD_DBOOT_KERN_MSG",
887 849 ret = BAM_MSG);
888 850 if (ret == BAM_ERROR) {
889 851 BAM_DPRINTF(("%s: cvt_kernel_line() "
890 852 "failed\n", fcn));
891 853 return (ret);
892 854 } else if (ret == BAM_MSG) {
893 855 msg = 1;
894 856 BAM_DPRINTF(("%s: BAM_MSG returned "
895 857 "from cvt_kernel_line()\n", fcn));
896 858 }
897 859 }
898 860 if (strcmp(line->cmd, menu_cmds[MODULE_CMD]) == 0) {
899 861 ret = cvt_module_line(line, entry);
900 862 INJECT_ERROR1("ADD_DBOOT_MOD_ERR",
901 863 ret = BAM_ERROR);
902 864 INJECT_ERROR1("ADD_DBOOT_MOD_MSG",
903 865 ret = BAM_MSG);
904 866 if (ret == BAM_ERROR) {
905 867 BAM_DPRINTF(("%s: cvt_module_line() "
906 868 "failed\n", fcn));
907 869 return (ret);
908 870 } else if (ret == BAM_MSG) {
909 871 BAM_DPRINTF(("%s: BAM_MSG returned "
910 872 "from cvt_module_line()\n", fcn));
911 873 msg = 1;
912 874 }
913 875 }
914 876
915 877 if (line == entry->end) {
916 878 BAM_DPRINTF(("%s: entry has ended\n", fcn));
917 879 break;
918 880 }
919 881 }
920 882 entry = find_matching_entry(entry->next, grubsign, grubroot,
921 883 root_opt);
922 884 }
923 885
924 886 ret = msg ? BAM_MSG : BAM_SUCCESS;
925 887 BAM_DPRINTF(("%s: returning ret = %d\n", fcn, ret));
926 888 return (ret);
927 889 }
↓ open down ↓ |
72 lines elided |
↑ open up ↑ |
928 890
929 891 /*ARGSUSED*/
930 892 error_t
931 893 upgrade_menu(menu_t *mp, char *osroot, char *menu_root)
932 894 {
933 895 char *osdev;
934 896 char *grubsign;
935 897 char *grubroot;
936 898 int ret1;
937 899 int ret2;
938 - int ret3;
939 900 const char *fcn = "upgrade_menu()";
940 901
941 902 assert(osroot);
942 903 assert(menu_root);
943 904
944 905 BAM_DPRINTF(("%s: entered. args: %s %s\n", fcn, osroot, menu_root));
945 906
946 907 /*
947 - * We only support upgrades. Xen may not be present
948 - * on smaller metaclusters so we don't check for that.
908 + * We only support upgrades.
949 909 */
950 910 if (bam_is_findroot != BAM_FINDROOT_PRESENT ||
951 911 bam_direct != BAM_DIRECT_DBOOT) {
952 912 bam_error(_("automated downgrade of GRUB menu to older "
953 913 "version not supported.\n"));
954 914 return (BAM_ERROR);
955 915 }
956 916
957 917 /*
958 918 * First get the GRUB signature
959 919 */
960 920 osdev = get_special(osroot);
961 921 INJECT_ERROR1("UPGRADE_OSDEV", osdev = NULL);
962 922 if (osdev == NULL) {
963 923 bam_error(_("cant find special file for mount-point %s\n"),
964 924 osroot);
965 925 return (BAM_ERROR);
966 926 }
967 927
968 928 grubsign = get_grubsign(osroot, osdev);
969 929 INJECT_ERROR1("UPGRADE_GRUBSIGN", grubsign = NULL);
970 930 if (grubsign == NULL) {
971 931 free(osdev);
972 932 bam_error(_("cannot find GRUB signature for %s\n"), osroot);
973 933 return (BAM_ERROR);
974 934 }
975 935
976 936 /* not fatal if we can't get grubroot */
977 937 grubroot = get_grubroot(osroot, osdev, menu_root);
↓ open down ↓ |
19 lines elided |
↑ open up ↑ |
978 938 INJECT_ERROR1("UPGRADE_GRUBROOT", grubroot = NULL);
979 939
980 940 free(osdev);
981 941
982 942 ret1 = bam_add_findroot(mp, grubsign,
983 943 grubroot, root_optional(osroot, menu_root));
984 944 INJECT_ERROR1("UPGRADE_ADD_FINDROOT", ret1 = BAM_ERROR);
985 945 if (ret1 == BAM_ERROR)
986 946 goto abort;
987 947
988 - if (bam_is_hv == BAM_HV_PRESENT) {
989 - ret2 = bam_add_hv(mp, grubsign, grubroot,
990 - root_optional(osroot, menu_root));
991 - INJECT_ERROR1("UPGRADE_ADD_HV", ret2 = BAM_ERROR);
992 - if (ret2 == BAM_ERROR)
993 - goto abort;
994 - } else
995 - ret2 = BAM_SUCCESS;
996 -
997 - ret3 = bam_add_dboot(mp, osroot, grubsign,
948 + ret2 = bam_add_dboot(mp, osroot, grubsign,
998 949 grubroot, root_optional(osroot, menu_root));
999 - INJECT_ERROR1("UPGRADE_ADD_DBOOT", ret3 = BAM_ERROR);
1000 - if (ret3 == BAM_ERROR)
950 + INJECT_ERROR1("UPGRADE_ADD_DBOOT", ret2 = BAM_ERROR);
951 + if (ret2 == BAM_ERROR)
1001 952 goto abort;
1002 953
1003 - if (ret1 == BAM_MSG || ret2 == BAM_MSG || ret3 == BAM_MSG) {
954 + if (ret1 == BAM_MSG || ret2 == BAM_MSG) {
1004 955 bam_error(_("one or more GRUB menu entries were not "
1005 956 "automatically upgraded\nFor details on manually "
1006 957 "updating entries, see %s\n"), MENU_URL(osroot));
1007 958 } else {
1008 959 bam_warn_hand_entries(mp, osroot);
1009 960 }
1010 961
1011 962 free(grubsign);
1012 963
1013 964 BAM_DPRINTF(("%s: returning ret = %d\n", fcn, BAM_WRITE));
1014 965 return (BAM_WRITE);
1015 966
1016 967 abort:
1017 968 free(grubsign);
1018 969 bam_error(_("error upgrading GRUB menu entries on %s. Aborting.\n"
1019 970 "For details on manually updating entries, see %s\n"), osroot,
1020 971 MENU_URL(osroot));
1021 972 return (BAM_ERROR);
1022 973 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX