1 /* bsect.c - Boot sector handling
3 * Copyright 1992-1998 Werner Almesberger
4 * Copyright 1999-2007 John Coffman
5 * Copyright 2009-2011 Joachim Wiedorn
8 * Licensed under the terms contained in the file 'COPYING'
9 * in the source directory.
14 #include <sys/types.h>
15 #include <sys/statfs.h>
23 #define _I386_STATFS_H /* two versions of statfs is not good ... */
41 #include "partition.h"
52 #if defined(LCF_UNIFY) || defined(LCF_BUILTIN)
59 static BOOT_SECTOR bsect,bsect_orig;
60 static MENUTABLE menuparams;
61 static DESCR_SECTORS descrs;
62 static char secondary_map[SECTOR_SIZE];
63 static unsigned char table[SECTOR_SIZE]; /* keytable & params */
65 static char *boot_devnam,*map_name;
66 static int use_dev_close = 0;
68 static int image_base = 0,image = 0;
69 static char temp_map[PATH_MAX+1];
70 static char *fallback[MAX_IMAGES];
71 static int fallbacks = 0;
72 static unsigned short stage_flags;
73 static int image_menu_space = MAX_IMAGES;
74 static char *getval_user;
75 static BOOT_PARAMS_2 param2;
76 static off_t here2; /* sector address of second stage loader */
77 static int adapter = -1; /* video adapter in use */
86 static PASSWORD *pwsave = NULL;
88 BUILTIN_FILE *select_loader(void)
90 BUILTIN_FILE *loader = &Third; /* MENU interface is the default */
91 char *install = cfg_get_strg(cf_options,"install");
92 char *bitmap = cfg_get_strg(cf_options,"bitmap");
95 if (bitmap) loader = &Bitmap;
97 else if (strstr(install,"text")) loader = &Second; /* text interface */
98 else if (strstr(install,"menu")) loader = &Third;
99 else if (strstr(install,"bmp") || bitmap) loader = &Bitmap; /* menu interface (MDA, EGA, VGA) */
101 adapter = get_video(); /* from probe.c */
103 if (adapter <= VIDEO_UNKNOWN && (verbose>=2 || loader==&Bitmap))
104 warn("Unable to determine video adapter in use in the present system.");
105 if (loader == &Third && adapter == VIDEO_CGA)
106 warn("Video adapter (CGA) is incompatible with the boot loader selected for\n"
107 " installation ('install = menu').");
108 if (loader == &Bitmap && adapter < VIDEO_MCGA && adapter > VIDEO_UNKNOWN)
109 warn("Video adapter (%s) is incompatible with the boot loader selected for\n"
110 " installation ('install = bitmap').", adapter==VIDEO_CGA ? "CGA" :
111 adapter==VIDEO_MDA ? "MDA" : "unknown");
117 /* kludge: 'append="..."' may not contain keywords acted upon by
118 the LILO boot loader -- except "mem=XXX"
121 static void check_options(char *options)
123 static char *disallow[] = {
127 "vga=", "kbd=", "lock", "nobd", NULL };
128 char *here, **dis = disallow;
131 if (verbose >= 5) printf("check_options: \"%s\"\n", options);
132 if (strlen(options) > COMMAND_LINE_SIZE-1) {
133 warn("Command line options > %d will be truncated.", COMMAND_LINE_SIZE-1);
136 here = strstr(options, *dis);
137 if (here && (here==options || here[-1] == ' ') ) {
138 if (here[3] == '=') error=2;
139 if (here[3] != '=' && (here[4]==' ' || here[4]==0) ) error=2;
141 if (*dis == disallow[0] && here[4]>='0' && here[4]<='9')
143 /* + (cfg_get_strg(cf_kernel,"initrd") != NULL ||
144 cfg_get_strg(cf_options,"initrd") != NULL) */
148 if (error>1) die ("APPEND or LITERAL may not contain \"%s\"", *dis);
151 warn("APPEND or LITERAL may not contain \"mem=\".");
159 static int getval(char **cp, int low, int high, int default_value, int factor)
164 if (factor && eflag) {
165 if (low==1) default_value--;
166 default_value *= factor;
169 else if (ispunct(**cp)) {
171 if (factor && eflag) {
172 if (low==1) default_value--;
173 default_value *= factor;
176 temp = strtol(*cp, cp, 0);
177 if (!factor) default_value = temp;
179 if (**cp == 'p' || **cp == 'P') {
181 default_value = temp;
185 default_value = (low==1 ? temp-1 : temp)*factor;
189 if (temp < low || temp > high)
190 die("%s: value out of range [%d,%d]", getval_user, low, high);
191 if (**cp && !ispunct(**cp)) die("Invalid character: \"%c\"", **cp);
194 if (verbose>=5) printf("getval: %d\n", default_value);
196 return default_value;
199 void bmp_do_timer(char *cp, MENUTABLE *menu)
202 if (eflag) menu->t_row = menu->t_col = -1; /* there is none, if not specified during edit */
203 } else if (strcasecmp(cp,"none")==0) {
204 menu->t_row = menu->t_col = -1; /* there is none, if specified as "none" */
206 getval_user = "bmp-timer";
207 menu->t_col = getval(&cp, 1, 76, menu->t_col, 8);
208 menu->t_row = getval(&cp, 1, 30, menu->t_row, 16);
210 if (!*cp && !eflag) return;
211 menu->t_fg = getval(&cp, 0, colormax, menu->fg, 0);
212 menu->t_bg = getval(&cp, 0, colormax, eflag?colormax^menu->t_fg:menu->t_bg, 0);
213 menu->t_sh = getval(&cp, 0, colormax, menu->t_fg, 0);
218 void bmp_do_table(char *cp, MENUTABLE *menu)
222 else return; /* dont change anything */
225 getval_user = "bmp-table";
226 menu->col = getval(&cp, 1, 80-MAX_IMAGE_NAME, menu->col/8 + 1, 8);
227 menu->row = getval(&cp, 1, 29, menu->row/16 + 1, 16);
229 menu->ncol = getval(&cp, 1, 80/(MAX_IMAGE_NAME+2), 1, 0);
230 menu->maxcol = getval(&cp, 3, MAX_IMAGES, (MAX_IMAGES+menu->ncol-1)/menu->ncol, 0);
231 menu->xpitch = getval(&cp, MAX_IMAGE_NAME+2, 80/menu->ncol, MAX_IMAGE_NAME+6, 8);
233 menu->ncol = getval(&cp, 1, 80/(MAX_IMAGE_NAME+1), menu->ncol, 0);
234 menu->maxcol = getval(&cp, 2, 30 - menu->row/16, eflag?30 - menu->row/16:menu->maxcol, 0);
235 menu->xpitch = getval(&cp, MAX_IMAGE_NAME+1, menu->ncol==1?80-menu->col/8:(80-menu->col/8-MAX_IMAGE_NAME*menu->ncol)/(menu->ncol-1)+MAX_IMAGE_NAME, menu->xpitch/8, 8);
236 menu->mincol = getval(&cp, 1, menu->maxcol, menu->mincol, 0);
238 if ((menu->row + menu->maxcol*16 > 480 ||
239 menu->col + (MAX_IMAGE_NAME+1)*8 + (menu->ncol-1)*menu->xpitch > 640))
240 warn("'bmp-table' may spill off screen");
244 void bmp_do_colors(char *cp, MENUTABLE *menu)
248 else return; /* dont change anything */
251 getval_user = "bmp-colors";
252 menu->fg = getval(&cp, 0, colormax, menu->fg, 0);
253 if (!*cp && !eflag) return;
254 menu->bg = getval(&cp, 0, colormax, menu->fg, 0);
255 menu->sh = getval(&cp, 0, colormax, menu->fg, 0);
257 menu->h_fg = getval(&cp, 0, colormax, menu->h_fg, 0);
258 if (!*cp && !eflag) return;
259 menu->h_bg = getval(&cp, 0, colormax, menu->h_fg, 0);
260 menu->h_sh = getval(&cp, 0, colormax, menu->h_fg, 0);
263 void pw_file_update(int passw)
268 if (verbose>=4) printf("pw_file_update: passw=%d\n", passw);
270 if (passw && !test && pw_file) {
271 if (fseek(pw_file,0L,SEEK_SET)) perror("pw_file_update");
273 for (walk=pwsave; walk; walk=walk->next) {
274 fprintf(pw_file, "label=<\"%s\">", walk->label);
275 for (i=0; i<MAX_PW_CRC; i++) fprintf(pw_file, " 0x%08X", walk->crc[i]);
276 fprintf(pw_file, "\n");
279 if (pw_file) fclose(pw_file);
282 void pw_fill_cache(void)
284 char line[MAX_TOKEN+1];
290 if (verbose>=5) printf("pw_fill_cache\n");
291 if (fseek(pw_file,0L,SEEK_SET)) perror("pw_fill_cache");
293 while (fgets(line,MAX_TOKEN,pw_file)) {
294 if (verbose>=5) printf(" %s\n", line);
295 brace = strrchr(line,'>');
296 label = strchr(line,'<');
297 if (label && label[1]=='"' && brace && brace[-1]=='"') {
299 if ( !(new = alloc_t(PASSWORD)) ) pdie("Out of memory");
303 new->label = stralloc(label+2);
304 if (verbose>=2) printf("Password file: label=%s\n", new->label);
306 for (i=0; i<MAX_PW_CRC; i++) {
307 new->crc[i] = strtoul(brace,&label,0);
311 else die("Ill-formed line in .crc file");
313 if (verbose >=5) printf("end pw_fill_cache\n");
316 static void hash_password(char *password, int crcval[])
319 static int poly[] = {CRC_POLY1, CRC_POLY2, CRC_POLY3, CRC_POLY4, CRC_POLY5};
323 int i = strlen(password);
327 shsUpdate((BYTE*)password, i);
330 for (j=0; j<MAX_PW_CRC; j++) {
333 crc32((unsigned char *)password, i, poly[j]);
334 #define PWTYPE "CRC-32"
337 #define PWTYPE "SHS-160"
340 if (j==0) printf("Password " PWTYPE " =");
341 printf(" %08X", crc);
344 if (verbose >= 2) printf("\n");
348 void pw_wipe(char *pass)
354 while (i) pass[--i]=0;
362 char *cp = getpass("");
364 char *acp = stralloc(cp);
366 while (i) cp[i--] = 0;
372 char buf[MAX_TOKEN+1];
377 while((ch=getchar())!='\n') if (i<MAX_TOKEN) buf[i++]=ch;
379 pass = stralloc(buf);
380 while (i) buf[--i]=0;
385 static void pw_get(char *pass, int crcval[], int option)
391 label = cfg_get_strg(cf_all, "label");
392 if (!label) label = cfg_get_strg(cf_top, "image");
393 if (!label) label = cfg_get_strg(cf_top, "other");
394 if (!label) die("Need label to get password");
395 if ((pass2 = strrchr(pass,'/'))) label = pass2+1;
397 for (walk=pwsave; walk; walk=walk->next) {
398 if (pass == walk->unique ||
399 (!walk->unique && !strcmp(walk->label,label) && (walk->unique=pass)) ) {
400 memcpy(crcval, walk->crc, MAX_PW_CRC*sizeof(int));
404 walk = alloc_t(PASSWORD);
405 if (!walk) die("Out of memory");
409 walk->label = stralloc(label);
411 printf("\nEntry for %s used null password\n", label);
415 printf(" *** Phrases don't match ***\n");
419 printf("Type passphrase: ");
421 printf("Please re-enter: ");
423 } while (strcmp(pass,pass2));
426 hash_password(pass, walk->crc);
428 memcpy(crcval, walk->crc, MAX_PW_CRC*sizeof(int));
432 static void retrieve_crc(int crcval[])
438 if (cfg_pw_open()) pw_fill_cache();
440 pass = cfg_get_strg(cf_all,"password");
441 if (pass) pw_get(pass,crcval,0);
442 else pw_get(cfg_get_strg(cf_options,"password"),crcval,1);
445 printf("Password found is");
446 for (i=0; i<MAX_PW_CRC; i++) printf(" %08X", crcval[i]);
453 static void open_bsect(char *boot_dev)
458 printf("Reading boot sector from %s\n",boot_dev ? boot_dev :
460 boot_devnam = boot_dev;
461 if (!boot_dev || !strcmp(boot_dev, "/") ) {
462 if (stat("/",&st) < 0) pdie("stat /");
463 if (MAJOR(st.st_dev) != MAJOR_MD &&
464 (st.st_dev & P_MASK(st.st_dev)) > PART_MAX)
465 die("Can't put the boot sector on logical partition 0x%04X",
467 fd = dev_open(&dev,boot_dev_nr = st.st_dev,O_RDWR);
468 boot_devnam = dev.name;
472 if ((fd = open(boot_dev,O_RDWR)) < 0)
473 die("open %s: %s",boot_dev,strerror(errno));
474 if (fstat(fd,&st) < 0) die("stat %s: %s",boot_dev,strerror(errno));
475 if (!S_ISBLK(st.st_mode)) boot_dev_nr = 0;
476 else boot_dev_nr = st.st_rdev;
478 /* new code to get boot device code */
479 /* plus geo_open will trigger VolumeMgmt (pf_hard_disk_scan) before the
480 boot sector is actually read; timing is very important */
483 geo_open(&geo, boot_devnam, O_RDONLY);
484 bios_boot = geo.device;
488 if (boot_dev_nr && !is_first(boot_dev_nr) )
489 warn("%s is not on the first disk",boot_dev ?
490 boot_dev : "current root");
491 if (read(fd,(char *) &bsect,SECTOR_SIZE) != SECTOR_SIZE)
492 die("read %s: %s",boot_dev ? boot_dev : dev.name,strerror(errno));
494 ireloc = part_nowrite(boot_devnam);
495 if (ireloc == PTW_DOS + PTW_NTFS) ireloc = PTW_DOS;
496 /* check for override (-F) command line flag */
497 if (ireloc>PTW_DOS && force_fs) {
498 int nowarn2 = nowarn;
501 warn("'-F' override used. Filesystem on %s may be destroyed.", boot_devnam);
502 if (!yesno("\nProceed? ",0)) exit(0);
510 void bsect_read(char *boot_dev,BOOT_SECTOR *buffer)
512 open_bsect(boot_dev);
518 static void menu_do_scheme(char *scheme, MENUTABLE *menu)
520 static char khar[] = "kbgcrmywKBGCRMYW";
524 /* order of color attributes is:
525 text, hilighted text, border, title
527 #define color(c) ((int)(strchr(khar,(int)(c))-khar))
529 at = &(menu->at_text);
530 for (i=0; i<4 && *scheme; i++) {
532 if (fg>=16) die("Invalid menu-scheme color: '%c'", *scheme);
533 if (*++scheme) bg = color(*scheme);
535 die("Invalid menu-scheme syntax");
537 if (bg>=16) die("Invalid menu-scheme color: '%c'", *scheme);
539 if (ispunct(*scheme)) scheme++;
540 else die("Invalid menu-scheme punctuation");
543 warn("menu-scheme BG color may not be intensified");
544 *at++ = ((bg<<4) | fg) & 0x7F;
546 /* check on the TEXT color */
547 if (menu->at_text == 0) {
548 warn("menu-scheme \"black on black\" changed to \"white on black\"");
549 menu->at_text = 0x07;
551 /* check on the HIGHLIGHT color */
552 if (menu->at_highlight == 0) menu->at_highlight = ((menu->at_text<<4)&0x70) | ((menu->at_text>>4)&0x0f);
553 /* check on the BORDER color */
554 if (menu->at_border == 0) menu->at_border = menu->at_text;
555 /* check on the TITLE color */
556 if (menu->at_title == 0) menu->at_title = menu->at_border;
558 strncpy(menu->menu_sig, "MENU", 4);
560 printf("Menu attributes: text %02X highlight %02X border %02X title %02X\n",
561 (int)menu->at_text, (int)menu->at_highlight,
562 (int)menu->at_border, (int)menu->at_title);
567 void bsect_open(char *boot_dev,char *map_file,char *install,int delay,
568 int timeout, int raid_offset)
570 static char coms[] = "0123";
571 static char parity[] = "NnOoEe";
573 "110\000150\000300\000600\0001200\0002400\0004800\0009600\000"
574 "19200\00038400\00057600\000115200\000?\000?\000?\000?\000"
578 int i, speed, bitmap, j, dataend;
579 int m_fd=0,kt_fd,sectors;
580 char *message,*colon,*serial,*walk,*this,*keytable,*scheme;
582 BITMAPFILEHEADER fhv;
584 BITMAPLILOHEADER lhv;
585 unsigned int timestamp;
587 BUILTIN_FILE *loader;
593 printf("sizeof(IMAGE_DESCR) = %d\n", sizeof(IMAGE_DESCR));
594 printf("sizeof(DESCR_SECTORS) = %d\n", sizeof(DESCR_SECTORS));
595 printf("MAX_IMAGES = %d\n", MAX_IMAGES);
597 image = image_base = i = 0;
598 memset(&menuparams, 0, sizeof(menuparams));
599 if (stat(map_file,&st) >= 0 && !S_ISREG(st.st_mode))
600 die("Map %s is not a regular file.",map_file);
601 open_bsect(boot_dev);
602 part_verify(boot_dev_nr,1);
603 if (ireloc>PTW_DOS) {
604 die("Filesystem would be destroyed by LILO boot sector: %s", boot_dev);
606 else if (ireloc==PTW_DOS) {
607 warn("boot record relocation beyond BPB is necessary: %s", boot_dev);
611 if ((colon = strrchr(map_name = map_file,':')) == NULL)
612 strcat(strcpy(temp_map,map_name),MAP_TMP_APP);
615 strcat(strcat(strcpy(temp_map,map_name),MAP_TMP_APP),colon+1);
618 map_create(temp_map);
619 temp_register(temp_map);
623 #if !defined(LCF_NOINSTDEF) || defined(LCF_BUILTIN)
626 die("No boot loader specified ('-i' or 'install =')");
630 timestamp = bsect.par_1.timestamp; /* preserve timestamp */
632 /* determine which secondary loader to use */
634 loader = select_loader();
636 printf("Using %s secondary loader\n",
637 loader==&Bitmap ? "BITMAP" :
638 loader==&Third ? "MENU" :
641 memcpy(&bsect, First.data, MAX_BOOT_SIZE);
643 bsect.par_1.timestamp = timestamp;
644 map_begin_section(); /* no access to the (not yet open) map file
645 required, because this map is built in memory */
646 here2 = map_insert_data (loader->data, loader->size);
647 memcpy(¶m2,loader->data,sizeof(param2));
649 /* write just the 4 bytes (sa6==2) */
650 sectors = map_write((SECTOR_ADDR*)secondary_map, (SECTOR_SIZE-4)/sizeof(SECTOR_ADDR)-2, 1, 2);
652 sectors = map_write((SECTOR_ADDR*)secondary_map, (SECTOR_SIZE-4)/sizeof(SECTOR_ADDR)-2, 1);
654 memcpy(secondary_map+SECTOR_SIZE-4, EX_MAG_STRING, 4);
656 /* fill in full size of secondary boot loader in paragraphs */
657 /*bsect.par_1.*/dataend = (sectors + 5 + (COMMAND_LINE_SIZE>256) + MAX_DESCR_SECS) * (SECTOR_SIZE/16);
660 printf("Secondary loader: %d sector%s (0x%0X dataend).\n",sectors,sectors == 1 ?
661 "" : "s", /*bsect.par_1.*/dataend*16);
662 stage_flags = ((BOOT_SECTOR*)(loader->data)) -> par_2.stage;
663 if ((stage_flags & 0xFF) != STAGE_SECOND)
664 die("Ill-formed boot loader; no second stage section");
666 if (verbose>=4) printf("install(2) flags: 0x%04X\n", (int)stage_flags);
670 if ((colon = strrchr(map_name = map_file,':')) == NULL)
671 strcat(strcpy(temp_map,map_name),MAP_TMP_APP);
674 strcat(strcat(strcpy(temp_map,map_name),MAP_TMP_APP),colon+1);
677 map_create(temp_map);
678 temp_register(temp_map);
682 map_add_sector(secondary_map);
684 /* write out six byte address */
685 (void) map_write(&bsect.par_1.secondary,1,0,1);
687 (void) map_write(&bsect.par_1.secondary,1,0);
690 /* if the state of the BIOS is DL_GOOD, always mark when boot==map
691 if the state of the BIOS is < DL_GOOD, never mark */
693 if ( bios_boot == bios_map &&
694 (bios_passes_dl == DL_GOOD
695 || (do_md_install && !(extra==X_MBR_ONLY ))
697 bsect.par_1.prompt |= FLAG_MAP_ON_BOOT;
698 if (bios_boot!=bios_map)
699 warn("The boot sector and map file are on different disks.");
700 if ( (bios_map & 0x80) && !do_md_install &&
701 !cfg_get_flag(cf_options, "static-bios-codes") ) /* hard disk & not raid master */
702 bsect.par_1.map_serial_no = serial_no[bios_map - 0x80];
704 printf("bios_boot = 0x%02X bios_map = 0x%02X map==boot = %d map S/N: %08X\n",
706 !!(bsect.par_1.prompt&FLAG_MAP_ON_BOOT),
707 bsect.par_1.map_serial_no);
709 /* code to get creation time of map file */
710 if (stat(temp_map, &st) < 0) die("Cannot get map file status");
711 param2.map_stamp = bsect.par_1.map_stamp = st.st_mtime;
712 if (verbose>=4) printf("Map time stamp: %08X\n", (int)bsect.par_1.map_stamp);
714 *(unsigned short *) &bsect.sector[BOOT_SIG_OFFSET] = BOOT_SIGNATURE;
715 message = cfg_get_strg(cf_options,"message");
716 scheme = cfg_get_strg(cf_options,"bitmap");
717 if (message && scheme) die("'bitmap' and 'message' are mutually exclusive");
719 bitmap = (loader==&Bitmap);
722 if (!(stage_flags & STAGE_FLAG_BMP4)) {
723 warn("Non-bitmap capable boot loader; 'bitmap=' ignored.");
730 printf("Mapping %s file %s",
731 bitmap ? "bitmap" : "message", message);
735 m_fd = geo_open(&geo,message,O_RDONLY);
736 if (fstat(m_fd,&st) < 0) die("stat %s: %s",message,strerror(errno));
737 /* the -2 below is because of GCC's alignment requirements */
738 i = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPHEADER)+sizeof(RGB)*16+
739 sizeof(BITMAPLILOHEADER);
740 if (bitmap || st.st_size>i) {
743 j = get_std_headers(m_fd, &fhv, &bmhv, &lhv);
744 if (j<0) die("read %s: %s", message, strerror(errno));
745 if (j==0 || j>2) { /* definitely a bitmap file */
746 BITMAPHEADER *bmh = &bmhv;
748 printf("width=%d height=%d planes=%d bits/plane=%d\n",
749 (int)bmh->width, (int)bmh->height,
750 (int)bmh->numBitPlanes, (int)bmh->numBitsPerPlane);
752 if (bmh->size == sizeof(BITMAPHEADER) &&
753 bmh->width==640 && bmh->height==480 &&
754 ((bits = bmh->numBitPlanes * bmh->numBitsPerPlane) == 4 ||
756 if (!bitmap) die("Message specifies a bitmap file");
757 if (bits>4 && adapter<VIDEO_VESA)
758 warn("Video adapter does not support VESA BIOS extensions needed for\n"
759 " display of 256 colors. Boot loader will fall back to TEXT only operation.");
761 else if (bitmap) die("Unsupported bitmap");
762 } else if (bitmap) die("Not a bitmap file");
764 i = bitmap ? MAX_KERNEL_SECS*SECTOR_SIZE : MAX_MESSAGE;
766 die("%s is too big (> %d bytes)",message,i);
767 param2.msg_len = bitmap ? (st.st_size+15)/16 : st.st_size;
770 map_add(&geo,0,((st.st_size)+SECTOR_SIZE-1)/SECTOR_SIZE);
772 map_insert_file (&geo,0,(st.st_size+SECTOR_SIZE-1)/SECTOR_SIZE);
774 sectors = map_end_section(&menuparams.msg,0);
776 printf("%s: %d sector%s.\n",bitmap?"Bitmap":"Message",
777 sectors,sectors == 1 ? "" : "s");
781 if (cfg_get_flag(cf_options,"el-torito-bootable-cd"))
782 param2.flag2 |= FLAG2_EL_TORITO;
783 if (cfg_get_flag(cf_options,"unattended")) {
784 param2.flag2 |= FLAG2_UNATTENDED;
786 warn("UNATTENDED used; setting TIMEOUT to 20s (seconds).");
791 serial = cfg_get_strg(cf_options,"serial");
793 if (!(stage_flags & STAGE_FLAG_SERIAL))
794 die("Serial line not supported by boot loader");
795 if (!*serial || !(this = strchr(coms,*serial)))
796 die("Invalid serial port in \"%s\" (should be 0-3)",serial);
797 else param2.port = (this-coms)+1;
798 param2.ser_param = SER_DFL_PRM;
800 if (serial[1] != ',')
801 die("Serial syntax is <port>[,<bps>[<parity>[<bits>]]]");
804 while (*walk && strncmp(serial+2,walk,(i=strlen(walk)))) {
808 if (!*walk) die("Unsupported baud rate");
809 param2.ser_param &= ~0xE4;
810 if (speed==16) speed -= 6; /* convert 56000 to 57600 */
811 param2.ser_param |= ((speed<<5) | (speed>>1)) & 0xE4;
813 /* check for parity specified */
815 if (!(this = strchr(parity,*serial)))
816 die("Serial speed = %s; valid parity values are N, O and E", walk);
817 i = (int)(this-parity)>>1;
818 if (i==2) i++; /* N=00, O=01, E=11 */
819 param2.ser_param &= ~(i&1); /* 7 bits if parity specified */
820 param2.ser_param |= i<<3; /* specify parity */
821 /* check if number of bits is there */
823 if (serial[1] != '7' && serial[1] != '8')
824 die("Only 7 or 8 bits supported");
825 if (serial[1]=='7') param2.ser_param &= 0xFE;
826 else param2.ser_param |= 0x01;
828 if (serial[2]) die("Syntax error in SERIAL");
831 if (verbose>=4) printf("Serial Param = 0x%02X\n",
832 (int)param2.ser_param);
834 if (delay < 20 && !cfg_get_flag(cf_options,"prompt")) {
835 warn("no PROMPT with SERIAL; setting DELAY to 20 (2 seconds)");
839 bsect.par_1.prompt |= cfg_get_flag(cf_options,"prompt") ? FLAG_PROMPT : 0;
840 if (cfg_get_flag(cf_options,"suppress-boot-time-BIOS-data")) {
841 warn("boot-time BIOS data will not be saved.");
842 bsect.par_1.prompt |= FLAG_NOBD;
844 if (!fetch() && (bios_map &
845 #if VERSION_MINOR>=50
846 bios_boot & /* if 'boot=/dev/fd0', force write */
849 bsect.par_1.prompt |= FLAG_BD_OKAY;
851 printf("BIOS data check was okay on the last boot\n");
855 printf("BIOS data check will include auto-suppress check\n");
857 /* set to LARGEMEM only if 'large-memory' ist set AND 'small-memory is not set */
858 if (cfg_get_flag(cf_options,"large-memory")
859 && !cfg_get_flag(cf_options,"small-memory")) {
860 #ifndef LCF_INITRDLOW
861 bsect.par_1.prompt |= FLAG_LARGEMEM;
863 warn("This LILO is compiled with INITRDLOW option, 'large-memory' ignored.");
866 bsect.par_1.prompt |= raid_flags;
867 bsect.par_1.raid_offset = raid_offset; /* to be modified in bsect_raid_update */
869 /* convert timeout in tenths of a second to clock ticks */
870 /* tick interval is 54.925 ms */
871 /* 54.925 * 40 -> 2197 */
872 /* 100 * 40 -> 4000 */
874 #define tick(x) ((x)*100/55)
876 #define tick(x) ((x)*4000/2197)
878 delay = delay==36000 ? 0xffff : tick(delay);
879 if (delay > 0xffff) die("Maximum delay is 59:59 (3599.5secs).");
880 else param2.delay = delay;
882 timeout = timeout==36000 ? 0xfffe : tick(timeout); /* -1 -> -1 ticks */
883 if (timeout == -1) param2.timeout = 0xffff;
884 else if (timeout >= 0xffff) die("Maximum timeout is 59:59 (3599.5secs).");
885 else param2.timeout = timeout;
887 /* keytable & parameter area setup */
889 if (!(keytable = cfg_get_strg(cf_options,"keytable"))) {
890 for (i = 0; i < 256; i++) table[i] = i;
893 if ((kt_fd = open(keytable,O_RDONLY)) < 0)
894 die("open %s: %s",keytable,strerror(errno));
895 if (read(kt_fd,table,256) != 256)
896 die("%s: bad keyboard translation table",keytable);
900 menu = (MENUTABLE*)&table[256];
901 memset(menu, 0, 256);
905 memcpy(&(menu->row), &(lhv.row), sizeof(lhv) - sizeof(lhv.size) - sizeof(lhv.magic));
907 if ((scheme = cfg_get_strg(cf_options,"menu-scheme"))) {
908 if (!(stage_flags & STAGE_FLAG_MENU))
909 warn("'menu-scheme' not supported by boot loader");
910 menu_do_scheme(scheme, menu);
912 if ((scheme = cfg_get_strg(cf_options,"menu-title"))) {
913 if (!(stage_flags & STAGE_FLAG_MENU))
914 warn("'menu-title' not supported by boot loader");
915 if (strlen(scheme) > MAX_MENU_TITLE)
916 warn("menu-title is > %d characters", MAX_MENU_TITLE);
917 strncpy(menu->title, scheme, MAX_MENU_TITLE);
918 menu->len_title = strlen(menu->title);
920 if ((scheme = cfg_get_strg(cf_options,"bmp-table"))) {
921 if (!(stage_flags & STAGE_FLAG_BMP4))
922 warn("'bmp-table' not supported by boot loader");
924 bmp_do_table(scheme, menu);
926 image_menu_space = menu->ncol * menu->maxcol;
927 if (verbose>=3) printf("image_menu_space = %d\n", image_menu_space);
929 if ((scheme = cfg_get_strg(cf_options,"bmp-colors"))) {
930 if (!(stage_flags & STAGE_FLAG_BMP4))
931 warn("'bmp-colors' not supported by boot loader");
933 bmp_do_colors(scheme, menu);
934 if ((scheme = cfg_get_strg(cf_options,"bmp-timer"))) {
935 if (!(stage_flags & STAGE_FLAG_BMP4))
936 warn("'bmp-timer' not supported by boot loader");
938 bmp_do_timer(scheme, menu);
941 map_add_sector(table);
942 (void) map_write(¶m2.keytab,1,0);
944 memset(&descrs,0,SECTOR_SIZE*MAX_DESCR_SECS);
945 if (cfg_get_strg(cf_options,"default")) image = image_base = 1;
946 if (verbose > 0) printf("\n");
950 static int dev_number(char *dev)
954 if (stat(dev,&st) >= 0) return st.st_rdev;
955 if (!isdigit(*dev)) die("Illegal 'root=' specification: %s", dev);
957 printf("Warning: cannot 'stat' device \"%s\"; trying numerical conversion\n", dev);
958 return to_number(dev);
962 static int get_image(char *name,char *label,IMAGE_DESCR *descr)
964 char *here,*deflt,*tmp;
965 int this_image,other,label_is_name=0;
970 here = strrchr(label = name,'/');
979 if (strchr(label,' ')) die("Image name, (which is actually the name) contains a blank character: '%s'", label);
991 if (strlen(label) > MAX_IMAGE_NAME) die("Image name, label, or alias is too long: '%s'",label);
992 for (uch=(unsigned char*)label; *uch; uch++) {
993 if (*uch<' ') die("Image name, label, or alias contains an illegal character: '%s'", label);
995 for (other = image_base; other <= image; other++) {
996 #ifdef LCF_IGNORECASE
997 if (!strcasecmp(label,descrs.d.descr[other].name))
999 if (!strcmp(label,descrs.d.descr[other].name))
1001 die("Duplicate label \"%s\"",label);
1002 if ((((descr->flags & FLAG_SINGLE) && strlen(label) == 1) ||
1003 (((descrs.d.descr[other].flags) & FLAG_SINGLE) &&
1004 strlen(descrs.d.descr[other].name) == 1)) &&
1005 #ifdef LCF_IGNORECASE
1006 toupper(*label) == toupper(*descrs.d.descr[other].name))
1008 *label == *descrs.d.descr[other].name)
1010 die("Single-key clash: \"%s\" vs. \"%s\"",label,
1011 descrs.d.descr[other].name);
1014 if (image_base && (deflt = cfg_get_strg(cf_options,"default")) &&
1015 #ifdef LCF_IGNORECASE
1016 !strcasecmp(deflt,label))
1018 !strcmp(deflt,label))
1020 this_image = image_base = 0;
1022 if (image == MAX_IMAGES)
1023 die("Only %d image names can be defined",MAX_IMAGES);
1024 if (image >= image_menu_space)
1025 die("Bitmap table has space for only %d images",
1027 this_image = image++;
1029 descrs.d.descr[this_image] = *descr;
1030 strcpy(descrs.d.descr[this_image].name,label);
1033 if ( (deflt = cfg_get_strg(cf_options,"vmdefault")) &&
1034 #ifdef LCF_IGNORECASE
1035 !strcasecmp(deflt,label)) {
1037 !strcmp(deflt,label)) {
1039 descrs.d.descr[this_image].flags |= FLAG_VMDEFAULT;
1040 param2.flag2 |= FLAG2_VIRTUAL;
1044 #ifdef LCF_NOKEYBOARD
1045 if ( (deflt = cfg_get_strg(cf_options,"nokbdefault")) &&
1046 #ifdef LCF_IGNORECASE
1047 !strcasecmp(deflt,label)) {
1049 !strcmp(deflt,label)) {
1051 descrs.d.descr[this_image].flags |= FLAG_NOKBDEFAULT;
1052 param2.flag2 |= FLAG2_NOKBD;
1060 static char options[SECTOR_SIZE]; /* this is ugly */
1063 static void bsect_common(IMAGE_DESCR *descr, int image)
1066 char *here,*root,*ram_disk,*vga,*password;
1067 char *literal,*append,*fback;
1068 char fallback_buf[SECTOR_SIZE];
1070 memset(descr, 0, sizeof(IMAGE_DESCR)); /* allocated on stack by caller */
1071 memset(fallback_buf,0,SECTOR_SIZE);
1072 memset(options,0,SECTOR_SIZE);
1074 if (image) { /* long section specific to 'image=' */
1077 if ((cfg_get_flag(cf_kernel,"read-only") && cfg_get_flag(cf_kernel,
1078 "read-write")) || (cfg_get_flag(cf_options,"read-only") && cfg_get_flag(
1079 cf_options,"read-write")))
1080 die("Conflicting READONLY and READ_WRITE settings.");
1082 if (cfg_get_flag(cf_kernel,"read-only") || cfg_get_flag(cf_options,
1083 "read-only")) strcat(options,"ro ");
1084 if (cfg_get_flag(cf_kernel,"read-write") || cfg_get_flag(cf_options,
1085 "read-write")) strcat(options,"rw ");
1086 if ((root = cfg_get_strg(cf_kernel,"root")) || (root = cfg_get_strg(
1087 cf_options,"root"))) {
1088 if (!strcasecmp(root,"current")) {
1089 if (stat("/",&st) < 0) pdie("stat /");
1090 sprintf(strchr(options,0),"root=%x ",(unsigned int) st.st_dev);
1092 else if (strlen(root)>12 && !strncmp(root,"/dev/mapper/",12)) {
1093 sprintf(strchr(options,0),"root=%s ", root);
1095 else if (strlen(root)>6 && !strncmp(root,"LABEL=",6)) {
1096 sprintf(strchr(options,0),"root=%s ", root);
1098 else if (strlen(root)>5 && !strncmp(root,"UUID=",5)) {
1099 sprintf(strchr(options,0),"root=%s ", root);
1102 sprintf(strchr(options,0),"root=%x ",dev_number(root));
1105 if ((ram_disk = cfg_get_strg(cf_kernel,"ramdisk")) || (ram_disk =
1106 cfg_get_strg(cf_options,"ramdisk")))
1107 sprintf(strchr(options,0),"ramdisk=%d ",to_number(ram_disk));
1109 if ((vga = cfg_get_strg(cf_kernel,"vga")) || (vga = cfg_get_strg(cf_options,
1112 warn("VGA mode presetting is not supported; ignoring 'vga='");
1114 descr->flags |= FLAG_VGA;
1115 if (!strcasecmp(vga,"normal")) descr->vga_mode = NORMAL_VGA;
1116 else if (!strcasecmp(vga,"ext") || !strcasecmp(vga,"extended"))
1117 descr->vga_mode = EXTENDED_VGA;
1118 else if (!strcasecmp(vga,"ask")) descr->vga_mode = ASK_VGA;
1119 else descr->vga_mode = to_number(vga);
1123 #ifdef LCF_BOOT_FILE
1124 if ((append = cfg_get_strg(cf_top, "image"))) {
1125 strcat(options, "BOOT_FILE=");
1126 strcat(options, append);
1127 strcat(options, " ");
1130 append_local = cfg_get_strg(cf_options,"append"); /* global, actually */
1131 if ((append = cfg_get_strg(cf_kernel,"append")) ||
1132 (append = append_local) ) {
1133 if (strlen(append) > COMMAND_LINE_SIZE-1) die("Command line options > %d", COMMAND_LINE_SIZE-1);
1134 strcat(strcat(options,append)," ");
1138 append = append_local; /* append == global append */
1139 if ((append_local = cfg_get_strg(cf_kernel,"addappend"))) {
1141 warn("ADDAPPEND used without global APPEND");
1142 if (strlen(options)+strlen(append_local) > SECTOR_SIZE-1) die("Command line options > %d", COMMAND_LINE_SIZE-1);
1143 strcat(options,append_local);
1147 } /* end of section specific to 'image=' */
1149 literal = cfg_get_strg(cf_kernel,"literal");
1150 if (literal) strcpy(options,literal);
1152 here = strchr(options,0);
1153 if (here[-1] == ' ') here[-1] = 0;
1155 check_options(options);
1157 if (cfg_get_flag(cf_kernel,"lock") || cfg_get_flag(cf_options,"lock")) {
1159 die("This LILO is compiled READONLY and doesn't support the LOCK "
1162 descr->flags |= FLAG_LOCK;
1166 if ((cfg_get_flag(cf_options,"restricted") &&
1167 cfg_get_flag(cf_options,"mandatory")) ||
1168 (cfg_get_flag(cf_all,"restricted") &&
1169 cfg_get_flag(cf_all,"mandatory")))
1170 die("MANDATORY and RESTRICTED are mutually exclusive");
1171 if (cfg_get_flag(cf_all,"bypass")) {
1172 if (cfg_get_flag(cf_all,"mandatory"))
1173 die("MANDATORY and BYPASS are mutually exclusive");
1174 if (cfg_get_flag(cf_all,"restricted"))
1175 die("RESTRICTED and BYPASS are mutually exclusive");
1176 if (!cfg_get_strg(cf_options,"password"))
1177 die("BYPASS only valid if global PASSWORD is set");
1179 if ((password = cfg_get_strg(cf_all,"password")) && cfg_get_flag(cf_all,"bypass"))
1180 die("PASSWORD and BYPASS not valid together");
1182 ( (password = cfg_get_strg(cf_options,"password")) &&
1183 !cfg_get_flag(cf_all,"bypass") ) ) {
1184 if (!*password) { /* null password triggers interaction */
1185 retrieve_crc((int*)descr->password_crc);
1187 hash_password(password, (int*)descr->password_crc );
1189 descr->flags |= FLAG_PASSWORD;
1193 if (cfg_get_flag(cf_all,"vmwarn")) {
1194 descr->flags |= FLAG_VMWARN;
1195 param2.flag2 |= FLAG2_VIRTUAL;
1197 if (cfg_get_flag(cf_all,"vmdisable")) {
1198 descr->flags |= FLAG_VMDISABLE;
1199 param2.flag2 |= FLAG2_VIRTUAL;
1201 if ( (descr->flags & FLAG_VMWARN) && (descr->flags & FLAG_VMDISABLE) )
1202 die ("VMWARN and VMDISABLE are not valid together");
1204 #ifdef LCF_NOKEYBOARD
1205 if (cfg_get_flag(cf_all,"nokbdisable")) {
1206 descr->flags |= FLAG_NOKBDISABLE;
1207 param2.flag2 |= FLAG2_NOKBD;
1212 if (cfg_get_flag(cf_all,"mandatory") || cfg_get_flag(cf_options,
1214 if (!password) die("MANDATORY is only valid if PASSWORD is set.");
1216 if (cfg_get_flag(cf_all,"restricted") || cfg_get_flag(cf_options,
1218 if (!password) die("RESTRICTED is only valid if PASSWORD is set.");
1219 if ((descr->flags & FLAG_PASSWORD) && !cfg_get_flag(cf_all,"mandatory"))
1220 descr->flags |= FLAG_RESTR;
1222 if (password && *password && config_read) {
1223 warn("%s should be readable only "
1224 "for root if using PASSWORD", config_file);
1225 config_read = 0; /* suppress further warnings */
1228 if (cfg_get_flag(cf_all,"restricted") || cfg_get_flag(cf_options,
1230 if (!password) die("RESTRICTED is only valid if PASSWORD is set.");
1231 descr->flags |= FLAG_RESTR;
1234 if (cfg_get_flag(cf_all,"bmp-retain") ||
1235 cfg_get_flag(cf_options,"bmp-retain")) descr->flags |= FLAG_RETAIN;
1237 if (cfg_get_flag(cf_all,"single-key") ||
1238 cfg_get_flag(cf_options,"single-key")) descr->flags |= FLAG_SINGLE;
1240 fback = cfg_get_strg(cf_kernel,"fallback");
1243 die("This LILO is compiled READONLY and doesn't support the FALLBACK "
1246 if (descr->flags & FLAG_LOCK)
1247 die("LOCK and FALLBACK are mutually exclusive");
1248 else descr->flags |= FLAG_FALLBACK;
1249 *(unsigned short *) fallback_buf = DC_MAGIC;
1250 strcpy(fallback_buf+2,fback);
1251 fallback[fallbacks++] = stralloc(fback);
1256 *(unsigned int *) descr->rd_size = 0; /* no RAM disk */
1258 descr->rd_size = 0; /* no RAM disk */
1260 descr->start_page = 0; /* load low */
1262 map_begin_section();
1263 map_add_sector(fallback_buf);
1264 map_add_sector(options);
1268 static void bsect_done(char *name,IMAGE_DESCR *descr)
1271 int this_image,this;
1273 if (!*name) die("Invalid image name.");
1274 alias = cfg_get_strg(cf_all,"alias");
1275 this = alias ? get_image(NULL,alias,descr) : -1;
1276 this_image = get_image(name,cfg_get_strg(cf_all,"label"),descr);
1277 if ((descr->flags & FLAG_SINGLE) &&
1278 strlen(descrs.d.descr[this_image].name) > 1 &&
1279 (!alias || strlen(alias) > 1))
1280 die("SINGLE-KEYSTROKE requires the label or the alias to be only "
1281 "a single character");
1283 printf("Added %s",descrs.d.descr[this_image].name);
1284 if (alias) printf(" (alias %s)",alias);
1286 if (descrs.d.descr[this_image].flags & FLAG_VMDEFAULT ||
1287 (this>=0 && (descrs.d.descr[this].flags & FLAG_VMDEFAULT)) )
1290 #ifdef LCF_NOKEYBOARD
1291 if (descrs.d.descr[this_image].flags & FLAG_NOKBDEFAULT ||
1292 (this>=0 && (descrs.d.descr[this].flags & FLAG_NOKBDEFAULT)) )
1295 if ( descrs.d.descr[this_image].flags & FLAG_TOOBIG ||
1296 (this>=0 && (descrs.d.descr[this].flags & FLAG_TOOBIG)) ) {
1297 /* show a question mark if small-memory is configured */
1298 #ifndef LCF_INITRDLOW
1299 if (!cfg_get_flag(cf_options,"small-memory"))
1305 /* here the default boot image can be set */
1306 if (this_image && this) putchar('\n');
1307 else printf(" *\n");
1310 printf("%4s<dev=0x%02x,hd=%d,cyl=%d,sct=%d>\n","",
1311 descr->start.device,
1314 descr->start.sector);
1315 if (*options) printf("%4s\"%s\"\n","",options);
1317 if (verbose >= 1) putchar('\n'); /* makes for nicer spacing */
1321 int bsect_number(void)
1323 /* -1 means default= did not exist */
1324 return image_base ? -1 : image;
1328 static void unbootable(void)
1332 fprintf(errstd,"\nCAUTION: The system is unbootable !\n");
1333 fprintf(errstd,"%9sRun LILO again to correct this.","");
1335 warn("The system is unbootable !\n"
1336 "\t Run LILO again to correct this.");
1342 void check_vmdefault(void)
1347 if ( (deflt = cfg_get_strg(cf_options,"vmdefault")) ) {
1348 for (i=0; i<image; ++i) {
1349 if (descrs.d.descr[i].flags & FLAG_VMDEFAULT) {
1350 if (descrs.d.descr[i].flags & FLAG_VMDISABLE)
1351 die("VMDEFAULT image cannot have VMDISABLE flag set");
1356 die("VMDEFAULT image does not exist.");
1361 #ifdef LCF_NOKEYBOARD
1362 void check_nokbdefault(void)
1367 if ( (deflt = cfg_get_strg(cf_options,"nokbdefault")) ) {
1368 for (i=0; i<image; ++i) {
1369 if (descrs.d.descr[i].flags & FLAG_NOKBDEFAULT) {
1370 if (descrs.d.descr[i].flags & FLAG_NOKBDISABLE)
1371 die("NOKBDEFAULT image cannot have NOKBDISABLE flag set");
1376 die("NOKBDEFAULT image does not exist.");
1382 void check_fallback(void)
1387 for (i = 0; i < fallbacks; i++) {
1388 for (start = fallback[i]; *start && *start == ' '; start++);
1390 for (end = start; *end && *end != ' '; end++);
1392 for (image = 0; image < MAX_IMAGES; image++)
1393 #ifdef LCF_IGNORECASE
1394 if (!strcasecmp(descrs.d.descr[image].name,start)) break;
1396 if (!strcmp(descrs.d.descr[image].name,start)) break;
1398 if (image == MAX_IMAGES) die("No image \"%s\" is defined",start);
1403 void check_unattended(void)
1405 if ( (descrs.d.descr[0].flags & (FLAG_PASSWORD + FLAG_RESTR) )
1407 && cfg_get_flag(cf_options,"unattended") )
1408 die("Mandatory PASSWORD on default=\"%s\" defeats UNATTENDED",
1409 descrs.d.descr[0].name);
1413 void bsect_update(char *backup_file, int force_backup, int pass)
1415 BOOT_SECTOR bsect_wr;
1417 static int timestamp = 0;
1420 temp = make_backup(backup_file, force_backup, &bsect_orig,
1421 boot_dev_nr, "boot sector");
1422 if (temp && !timestamp) bsect.par_1.timestamp = timestamp = temp;
1426 # error "Bios Translation algorithms require '-DUNIFY' in Makefile"
1428 if (pass<1) { /* BIOS_TT logic */
1429 MENUTABLE *menu = &menuparams;
1430 map_descrs(&descrs, menu->mt_descr, &menuparams.dflcmd);
1431 menuparams.raid_dev_mask = raid_mask((int*)menuparams.raid_offset);
1432 memcpy(menuparams.serial_no, serial_no, sizeof(serial_no));
1433 memcpy(table+256, &menuparams, sizeof(menuparams));
1434 ((int*)table)[SECTOR_SIZE/sizeof(int)-2] = crc32(table, SECTOR_SIZE-2*sizeof(int), CRC_POLY1);
1435 map_begin_section();
1436 map_add_sector(table);
1438 /* still use 5 byte address */
1439 (void) map_write(¶m2.keytab,1,0,0);
1441 (void) map_write(¶m2.keytab,1,0);
1443 map_close(¶m2, here2);
1444 } /* if (pass<1) ... */
1447 if (lseek(fd,0,SEEK_SET) < 0)
1449 boot_devnam ? boot_devnam : dev.name,
1454 bsect.par_1.cli == 0xFA
1456 /* perform the relocation of the boot sector */
1457 int len = bsect.par_1.code_length;
1458 int space = BOOT_SIG_OFFSET - len;
1460 if (len==0) die ("First stage loader is not relocatable.");
1462 space &= 0xFFF0; /* roll back to paragraph boundary */
1463 bsect_wr = bsect_orig;
1464 memcpy(&bsect_wr.sector[space], &bsect, len);
1465 if (space <= 0x80) {
1466 bsect_wr.sector[0] = 0xEB; /* jmp short */
1467 bsect_wr.sector[1] = space - 2;
1468 bsect_wr.sector[2] = 0x90; /* nop */
1470 bsect_wr.sector[0] = 0xE9; /* jmp near */
1471 *(short*)&bsect_wr.sector[1] = space - 3;
1473 if (bsect_wr.sector[space+1] == 0xEB) { /* jmp short */
1475 space += (signed)bsect_wr.sector[space+2] + 3;
1476 if (bsect_wr.sector[space] == 0xB8) /* mov ax,#07C0 */
1477 *(short*)&bsect_wr.sector[space+1] += len;
1479 /*** bsect = bsect_orig; ***/
1480 if (verbose >= 1) printf("Boot sector relocation performed\n");
1482 else bsect_wr = bsect;
1485 /* failsafe check */
1488 printf("Failsafe check: boot_dev_nr = 0x%04x 0x%04x\n", boot_dev_nr, has_partitions(boot_dev_nr));
1489 /*** if (do_md_install) ***/ {
1490 printf("map==boot = %d map s/n = %08X\n",
1491 !!(bsect_wr.par_1.prompt & FLAG_MAP_ON_BOOT),
1492 bsect_wr.par_1.map_serial_no
1498 has_partitions(boot_dev_nr) &&
1499 (P_MASK(boot_dev_nr)&boot_dev_nr)==0 &&
1500 memcmp(bsect.sector+MAX_BOOT_SIZE, bsect_wr.sector+MAX_BOOT_SIZE, 64+8)
1502 die("LILO internal error: Would overwrite Partition Table");
1503 /* failsafe check */
1505 sync(); /* this may solve possible kernel buffer problem */
1507 if (!test && write(fd, (char *)&bsect_wr, SECTOR_SIZE) != SECTOR_SIZE)
1508 die("write %s: %s",boot_devnam ? boot_devnam : dev.name,
1511 } /* if (pass>=0) ... */
1513 if (use_dev_close) dev_close(&dev);
1514 else if (close(fd) < 0) {
1516 die("close %s: %s",boot_devnam,strerror(errno));
1524 pw_file_update(passw);
1525 temp_unregister(temp_map);
1526 if (rename(temp_map,map_name) < 0) {
1528 die("rename %s %s: %s",temp_map,map_name,strerror(errno));
1531 /* (void) sync(); Now handled in lilo.c (atexit(sync)) */
1532 if (verbose>=6) printf("End bsect_update\n");
1537 void bsect_cancel(void)
1540 map_descrs(&descrs, bsect.par_1.descr, &bsect.par_1.dflcmd);
1543 if (!use_dev_close) (void) close(fd);
1544 else dev_close(&dev);
1545 temp_unregister(temp_map);
1546 if (verbose<9) (void) remove(temp_map);
1550 static int present(char *var)
1554 if (!(path = cfg_get_strg(cf_top,var))) die("No variable \"%s\"",var);
1555 if (!access(path,F_OK)) return 1;
1556 if (!cfg_get_flag(cf_all,"optional") && !cfg_get_flag(cf_options,
1557 "optional")) return 1;
1558 if (verbose >= 0) printf("Skipping %s\n",path);
1563 static int initrd_present(void)
1567 path = cfg_get_strg(cf_kernel, "initrd");
1568 if (!path) path = cfg_get_strg(cf_options, "initrd");
1569 if (!path) return 1;
1570 if (!access(path,F_OK)) return 1;
1571 if (!cfg_get_flag(cf_all,"optional") && !cfg_get_flag(cf_options,
1572 "optional")) return 1;
1573 if (verbose >= 0) printf("Skipping %s\n", cfg_get_strg(cf_top, "image"));
1583 /* memset(&descr, 0, sizeof(descr)); Done in "bsect_common" */
1585 (void) cfg_parse(cf_image);
1586 if (present("image") && initrd_present()) {
1587 bsect_common(&descr, 1);
1588 descr.flags |= FLAG_KERNEL;
1589 name = cfg_get_strg(cf_top,"image");
1590 if (!cfg_get_strg(cf_image,"range")) boot_image(name,&descr);
1591 else boot_device(name,cfg_get_strg(cf_image,"range"),&descr);
1592 bsect_done(name,&descr);
1601 char *name, *loader;
1603 /* memset(&descr, 0, sizeof(descr)); Done in "bsect_common" */
1605 cfg_init(cf_kernel); /* clear kernel parameters */
1606 curr_drv_map = curr_prt_map = 0;
1607 (void) cfg_parse(cf_other);
1608 if (present("other")) {
1609 bsect_common(&descr, 0);
1610 name = cfg_get_strg(cf_top,"other");
1611 loader = cfg_get_strg(cf_other,"loader");
1612 if (!loader) loader = cfg_get_strg(cf_options,"loader");
1613 boot_other(loader,name,cfg_get_strg(cf_other,"table"),&descr);
1614 bsect_done(name,&descr);
1620 void bsect_uninstall(char *boot_dev,char *backup_file,int validate)
1623 char temp_name[PATH_MAX+1];
1626 open_bsect(boot_dev);
1627 if (*(unsigned short *) &bsect.sector[BOOT_SIG_OFFSET] != BOOT_SIGNATURE)
1628 die("Boot sector of %s does not have a boot signature",boot_dev ?
1629 boot_dev : dev.name);
1630 if (!strncmp(bsect.par_1.signature-4,"LILO",4))
1631 die("Boot sector of %s has a pre-21 LILO signature",boot_dev ?
1632 boot_dev : dev.name);
1633 if (strncmp(bsect.par_1.signature,"LILO",4))
1634 die("Boot sector of %s doesn't have a LILO signature",boot_dev ?
1635 boot_dev : dev.name);
1637 sprintf(temp_name,BACKUP_DIR "/boot.%04X",boot_dev_nr);
1638 backup_file = temp_name;
1640 if ((bck_file = open(backup_file,O_RDONLY)) < 0)
1641 die("open %s: %s",backup_file,strerror(errno));
1642 if (fstat(bck_file,&st) < 0)
1643 die("fstat %s: %s",backup_file,strerror(errno));
1644 if (validate && st.st_mtime != bsect.par_1.timestamp)
1645 die("Timestamp in boot sector of %s differs from date of %s\n"
1646 "Try using the -U option if you know what you're doing.",boot_dev ?
1647 boot_dev : dev.name,backup_file);
1648 if (verbose > 0) printf("Reading old boot sector.\n");
1649 if (read(bck_file,(char *) &bsect,PART_TABLE_OFFSET) != PART_TABLE_OFFSET)
1650 die("read %s: %s",backup_file,strerror(errno));
1651 if (lseek(fd,0,SEEK_SET) < 0)
1652 die("lseek %s: %s",boot_dev ? boot_dev : dev.name,strerror(errno));
1653 if (verbose > 0) printf("Restoring old boot sector.\n");
1654 if (write(fd,(char *) &bsect,PART_TABLE_OFFSET) != PART_TABLE_OFFSET)
1655 die("write %s: %s",boot_dev ? boot_dev : dev.name,strerror(errno));
1656 if (use_dev_close) dev_close(&dev);
1657 else if (close(fd) < 0) {
1659 die("close %s: %s",boot_devnam,strerror(errno));
1665 void bsect_raid_update(char *boot_dev, unsigned int raid_offset,
1666 char *backup_file, int force_backup, int pass, int mask)
1668 BOOT_SECTOR bsect_save;
1670 int prompt = bsect.par_1.prompt;
1672 if (pass<0) bsect_update(backup_file, force_backup, pass);
1675 bsect_save = bsect; /* save the generated boot sector */
1676 open_bsect(boot_dev);
1677 memcpy(&bsect, &bsect_save, MAX_BOOT_SIZE); /* update the subject boot sector */
1678 bsect.par_1.raid_offset = raid_offset; /* put in the new partition offset */
1679 bsect.par_1.prompt &= mask; /* clear all RAID flags */
1680 bsect.par_1.prompt |= raid_flags; /* update the raid flags */
1682 bios = (raid_flags&FLAG_RAID_DEFEAT) ? bios_map : bios_boot;
1683 if (!cfg_get_flag(cf_options, "static-bios-codes")) {
1684 if (verbose>=2) printf("Using s/n from device 0x%02X\n", bios);
1685 bsect.par_1.map_serial_no = serial_no[bios - 0x80];
1689 /* lines added 22.5.7 */
1690 ((SECTOR_ADDR6*)&bsect.par_1.secondary)->device = bios;
1692 /* lines added 22.5.6 */
1693 bsect.par_1.secondary.device &= ~DEV_MASK;
1694 bsect.par_1.secondary.device |= bios;
1696 /* ************************************ */
1698 *(unsigned short *) &bsect.sector[BOOT_SIG_OFFSET] = BOOT_SIGNATURE;
1701 if (pass<0) pass = -pass;
1703 bsect_update(backup_file, force_backup, pass);
1705 bsect.par_1.prompt = prompt; /* restore the flag byte */