0e6c2424142cab9764c694851fd2f5a7e76fee2f
[rrq/maintain_lilo.git] / src / lilo.c
1 /* lilo.c  -  LILO command-line parameter processing
2  * 
3  * Copyright 1992-1998 Werner Almesberger
4  * Copyright 1999-2007 John Coffman
5  * Copyright 2009-2011 Joachim Wiedorn
6  * All rights reserved.
7  * 
8  * Licensed under the terms contained in the file 'COPYING'
9  * in the source directory.
10  */
11
12 #define _GNU_SOURCE
13 #include <stdlib.h>
14 #include <unistd.h>
15 #include <stdio.h>
16 #include <string.h>
17 #include <ctype.h>
18 #include <fcntl.h>
19 #include <errno.h>
20 #include <time.h>
21 #include <limits.h>
22 #include <dirent.h>
23 /*#include <asm/page.h>*/
24
25 #include "config.h"
26 #include "lilo.h"
27 #include "common.h"
28 #include "cfg.h"
29
30 #if !__MSDOS__
31 #include "raid.h"
32 #include "boot.h"
33 #include "device.h"
34 #include "flags.i"
35 #include "geometry.h"
36 #endif /* !__MSDOS__ */
37 #include "map.h"
38 #if !__MSDOS__
39 #include "bsect.h"
40 #include "identify.h"
41 #include "partition.h"
42 #include "probe.h"
43 #include "temp.h"
44 #include "loader.h"
45 #include "md-int.h"
46 #include "edit.h"
47 #endif /* !__MSDOS__ */
48
49
50 char *config_file;              /* actual name of the config file */
51 int config_read;                /* readable by other than root */
52 FILE *errstd;
53
54 static void configuration(void)
55 {
56 #if VERSION_MINOR>=50 && !__MSDOS__
57 {
58                 printf(
59                 "-DBOOT_PARAMS_1=%d -DBOOT_PARAMS_2=%d  PATH_MAX=%d"
60                   "\n"
61                   ,
62                   (int)sizeof(BOOT_PARAMS_1),
63                   (int)sizeof(BOOT_PARAMS_2),
64                   PATH_MAX
65                      );
66 }
67 {
68 #include "bitmap.h"
69         RGB pal[16];
70         RGB2 pal2[16];
71         
72         printf("\nBMFH=%d BMH=%d BMH2=%d RGB=%d(%d) RGB2=%d(%d) LH=%d\n",
73         (int)sizeof(BITMAPFILEHEADER),
74         (int)sizeof(BITMAPHEADER),
75         (int)sizeof(BITMAPHEADER2),
76         (int)sizeof(RGB),
77         (int)sizeof(pal),
78         (int)sizeof(RGB2),
79         (int)sizeof(pal2),
80         (int)sizeof(BITMAPLILOHEADER) );
81         printf("\nBPB=%d BP_DOS=%d\n",
82                 (int)sizeof(BIOS_PARAMETER_BLOCK),
83                 (int)sizeof(BOOT_PARAMS_DOS)
84                   );
85 }
86 #ifdef LCF_FIRST6
87         printf("\nSECTOR_ADDR6=%d\n", (int)sizeof(SECTOR_ADDR6));
88 #endif
89
90 #endif /* VERSION_MINOR>=50 && !__MSDOS__ */
91
92 #if !__MSDOS__
93 {
94   unsigned int j;
95   if (verbose>=5) {
96     if (crc(First.data,First.size)) {
97         j = crc(First.data,First.size-4);
98         brev(j);
99         printf("1=0x%x\n", j);
100     }
101     if (crc(Second.data,Second.size)) {
102         j = crc(Second.data,Second.size-4);
103         brev(j);
104         printf("2=0x%x\n", j);
105     }
106     if (crc(Third.data,Third.size)) {
107         j = crc(Third.data,Third.size-4);
108         brev(j);
109         printf("3=0x%x\n", j);
110     }
111     if (crc(Bitmap.data,Bitmap.size)) {
112         j = crc(Bitmap.data,Bitmap.size-4);
113         brev(j);
114         printf("B=0x%x\n", j);
115     }
116     if (crc(Chain.data,Chain.size)) {
117         j = crc(Chain.data,Chain.size-4);
118         brev(j);
119         printf("C=0x%x\n", j);
120     }
121     if (crc(Mbr.data,Mbr.size)) {
122         j = crc(Mbr.data,Mbr.size-4);
123         brev(j);
124         printf("M=0x%x\n", j);
125     }
126     if (crc(Mbr2.data,Mbr2.size)) {
127         j = crc(Mbr2.data,Mbr2.size-4);
128         brev(j);
129         printf("N=0x%x\n\n", j);
130     }
131   }
132 }
133
134 #if BETA_TEST
135 {
136     int i, j, k=0;
137 extern int has_partitions_beta(dev_t dev);      /* defined in geometry.c */
138
139
140     printf("\n");
141     for (i=0; i<256; i++) {
142         if ( has_partitions_beta(MKDEV(i,0)) != has_partitions(MKDEV(i,0)) ) {
143             printf("Major device = %d is not configured.\n", i);
144             k ++;
145         }
146     }
147     printf("%sk = %d (should be 0)\n\n", k?"ERROR: ":"", k);
148     for (i=0, j=0; i<40960; i+=17) {
149         dev_t dev;
150         int major, minor;
151         for (k=0; k<81920; k+=19) {
152             dev = MKDEV(i,k);
153             major = MAJOR(dev);
154             minor = MINOR(dev);
155             if (major != i  ||  minor != k) {
156                 printf("ERROR: (%d,%d) -> (%d,%d)\n",
157                     i, k, major, minor);
158                 j++;
159             }
160         }
161     }
162     if (j==0) printf("MKDEV check passed\n");
163 }
164 #endif
165
166 #if VERSION_MINOR>=50
167 {
168         dev_t dev; int i;
169         BOOT_VOLID x;
170         BOOT_SECTOR b;
171         dev = 0xFFF0;
172         i = dev;
173         printf("dev_t is %ssigned size=%d  i=%08X\n", i==0xFFF0 ? "un" : "", (int)sizeof(dev_t), i);
174         printf("size of BOOT_VOLID = %d   BOOT_SECTOR = %d\n", (int)sizeof(x), (int)sizeof(b));
175         printf("Size of MENUTABLE = %d\n", (int)sizeof(MENUTABLE));
176 }
177 #endif
178                 printf("\nCFLAGS = " CFLAGS "\n");
179 #if defined(LCF_DEVMAPPER) && defined(HAS_LIBDEVMAPPER_H)
180                 printf("With");
181 #else
182                 printf("Without");
183 #endif
184                 printf(" device-mapper\n");
185                 printf("\nglibc version %d.%d\n", __GLIBC__, __GLIBC_MINOR__);
186                 printf("Kernel Headers included from  %d.%d.%d\n",
187                         LINUX_VERSION_CODE>>16,
188                         LINUX_VERSION_CODE>>8 & 255,
189                         LINUX_VERSION_CODE & 255);
190                 printf("Maximum Major Device = %d\n", MAJOR(~0UL));
191 #endif /* !__MSDOS__ */
192                 printf("MAX_IMAGES = %d\t\tc=%d, s=%d, i=%d, "
193                                 "l=%d, ll=%d, f=%d, d=%d, ld=%d\n",
194                         MAX_IMAGES, (int)sizeof(char),
195                         (int)sizeof(short), (int)sizeof(int),
196                         (int)sizeof(long), (int)sizeof(
197 #if !__MSDOS__
198                         long
199 #endif /* !__MSDOS__ */
200                              long),
201                         (int)sizeof(float), (int)sizeof(double),
202                         (int)sizeof(long double)
203                         );
204                 printf("IMAGE_DESCR = %d   DESCR_SECTORS = %d\n\n",
205                         (int)sizeof(IMAGE_DESCR), (int)sizeof(DESCR_SECTORS));
206 }
207
208 #if !__MSDOS__
209
210 static void show_other(int fd)
211 {
212     BOOT_SECTOR buf[SETUPSECS-1];
213     const unsigned char *drvmap;
214     const unsigned char *prtmap;
215
216     if (read(fd,buf,sizeof(buf)) != sizeof(buf))
217         die("Read on map file failed (access conflict ?) 1");
218     if (!strncmp(buf[0].par_c.signature-4,"LILO",4)) {
219         printf("    Pre-21 signature (0x%02x,0x%02x,0x%02x,0x%02x)\n",
220           buf[0].par_c.signature[0],buf[0].par_c.signature[1],
221           buf[0].par_c.signature[2],buf[0].par_c.signature[3]);
222         return;
223     }
224     if (strncmp(buf[0].par_c.signature,"LILO",4)) {
225         printf("    Bad signature (0x%02x,0x%02x,0x%02x,0x%02x)\n",
226           buf[0].par_c.signature[0],buf[0].par_c.signature[1],
227           buf[0].par_c.signature[2],buf[0].par_c.signature[3]);
228         return;
229     }
230     drvmap = ((unsigned char *) buf+buf[0].par_c.drvmap);
231     prtmap = drvmap+2*(DRVMAP_SIZE+1);
232     while (drvmap[0] && drvmap[1]) {
233         if (drvmap[0]==0xFF && drvmap[1]==0xFF) {
234             if (drvmap[3]==0xFF) printf("    Master-Boot:  This BIOS drive will always appear as 0x80 (or 0x00)\n");
235             else printf("    Boot-As:  This BIOS drive will always appear as 0x%02X\n", drvmap[3]);
236             drvmap += 4;
237         } else {
238             printf("    BIOS drive 0x%02X is mapped to 0x%02X\n",drvmap[0],
239                                                 drvmap[1]);
240             drvmap += 2;
241         }
242     }
243     /* fix VERY old bug -- offset of 0 in PT is okay */
244     while (prtmap[0] /*** && prtmap[1] ***/ ) {
245         printf("    BIOS drive 0x%02x, offset 0x%x: 0x%02x -> 0x%02x\n",
246           prtmap[0],prtmap[1]+PART_TABLE_OFFSET,prtmap[2],prtmap[3]);
247         prtmap += 4;
248     }
249 }
250 #endif /* !__MSDOS__ */
251
252 static void show_images(char *map_file)
253 {
254 #if !__MSDOS__
255     DESCR_SECTORS descrs;
256     BOOT_SECTOR boot;
257     MENUTABLE menu;
258     BOOT_PARAMS_2 param2;
259     GEOMETRY geo;
260     SECTOR_ADDR addr[4];
261     char buffer[SECTOR_SIZE];
262 #else /* __MSDOS */
263 static DESCR_SECTORS descrs;
264 static char buffer[SECTOR_SIZE];
265 #endif /*__MSDOS__ */
266     char *name;
267     int fd,image;
268     int tsecs;
269     int tlinear, tlba32;
270     unsigned short flags;
271     time_t Time;
272
273 #if !__MSDOS__
274     fd = geo_open(&geo,map_file,O_RDONLY);
275 #else  /* __MSDOS__ */
276     if ((fd = open(map_file,O_RDONLY))<=0)
277         die("Cannot open map file: %s", map_file);
278 #endif /* __MSDOS__ */
279     if (read(fd,buffer,SECTOR_SIZE) != SECTOR_SIZE)
280         die("read cmdline %s: %s",map_file,strerror(errno));
281     if (read(fd,(char*)&descrs,sizeof(descrs)) != sizeof(descrs))
282         die("read descrs %s: %s",map_file,strerror(errno));
283 #if !__MSDOS__
284     if (lseek(fd, SECTOR_SIZE, SEEK_CUR) <= 0)  /* skip zero sector */
285         die("lseek over zero sector %s: %s",map_file,strerror(errno));
286     if (read(fd,(char*)&param2,sizeof(param2)) != sizeof(param2))
287         die("read second params %s: %s",map_file,strerror(errno));
288     if (lseek(fd, - sizeof(menu), SEEK_END) <= 0)
289         die("lseek keytable %s: %s",map_file,strerror(errno));
290     if (read(fd,(char*)&menu,sizeof(menu)) != sizeof(menu))
291         die("read keytable %s: %s",map_file,strerror(errno));
292     tlba32  = (descrs.d.descr[0].start.device & LBA32_FLAG) != 0;
293     tlinear = !tlba32 && (descrs.d.descr[0].start.device & LINEAR_FLAG);
294     if (tlinear != linear  ||  tlba32 != lba32) {
295         printf("Warning: mapfile created with %s option\n",
296                tlinear?"linear":tlba32?"lba32":"no linear/lba32");
297         linear = tlinear;  lba32 = tlba32;
298     }
299     if (verbose) {
300         bsect_read(cfg_get_strg(cf_options,"boot"),&boot);
301 #if 1
302         if (boot.par_1.cli != 0xFA) {   /* relocation happened */
303             int len, offset=0;
304             if (boot.sector[0] == 0xEB)         /* jmp short */
305                 offset = boot.sector[1]+2;
306             else if (boot.sector[0] == 0xE9)    /* jmp near */
307                 offset = *(short*)&boot.sector[1] + 3;
308             else die("Cannot undo boot sector relocation.");
309             len = SECTOR_SIZE - offset;
310             memmove(&boot, &boot.sector[offset], len);
311             if (boot.par_1.cli != 0xFA)
312                 die("Cannot recognize boot sector.");
313         }
314 #endif
315 #if 1
316         Time = boot.par_1.map_stamp;
317         printf("Installed:  %s\n", ctime(&Time));
318 #else
319         printf("Installed:  %s\n", ctime((time_t*)&boot.par_1.map_stamp));
320 #endif
321         printf("Global settings:\n");
322         tsecs = (param2.delay*2197+3999)/4000;
323         printf("  Delay before booting: %d.%d seconds\n",tsecs/10,tsecs % 10);
324         if (param2.timeout == 0xffff) printf("  No command-line timeout\n");
325         else {
326             tsecs = (param2.timeout*2197+3999)/4000;
327             printf("  Command-line timeout: %d.%d seconds\n",tsecs/10,
328               tsecs % 10);
329         }
330         printf("  %snattended booting\n", param2.flag2&FLAG2_UNATTENDED ? "U" : "No u");
331         printf("  %sPC/AT keyboard hardware prescence check\n", param2.flag2&FLAG2_NOKBD ? "" : "No ");
332         if (boot.par_1.prompt & FLAG_PROMPT) printf("  Always enter boot prompt\n");
333         else printf("  Enter boot prompt only on demand\n");
334         printf("  Boot-time BIOS data%s saved\n",
335                 boot.par_1.prompt & FLAG_NOBD ? " NOT" : "");
336         printf("  Boot-time BIOS data auto-suppress write%s bypassed\n",
337                 boot.par_1.prompt & FLAG_BD_OKAY ? "" : " NOT");
338         printf("  Large memory (>15M) is%s used to load initial ramdisk\n", 
339                 boot.par_1.prompt & FLAG_LARGEMEM ? "" : " NOT");
340         printf("  %sRAID installation\n",
341                 boot.par_1.prompt & FLAG_RAID ? "" : "Non-");
342         printf("  Boot device %s be used for the Map file\n",
343                 boot.par_1.prompt & FLAG_MAP_ON_BOOT ? "WILL" : "will not");
344         if (!param2.port) printf("  Serial line access is disabled\n");
345         else printf("  Boot prompt can be accessed from COM%d\n",
346               param2.port);
347         if (!param2.msg_len) printf("  No message for boot prompt\n");
348         else if (!cfg_get_strg(cf_options,"bitmap"))
349             printf("  Boot prompt message is %d bytes\n",param2.msg_len);
350         else printf("  Bitmap file is %d paragraphs (%d bytes)\n",
351                         param2.msg_len, 16*param2.msg_len);
352 /* 22.6.2 begin */
353         if (*(unsigned short *) buffer != DC_MAGIC /* || !buffer[2] */)
354 /* 22.6.2 end */
355             printf("  No default boot command line\n");
356         else printf("  Default boot command line: \"%s\"\n",buffer+2);
357         if (verbose>=3) {
358             printf("Serial numbers %08X\n", menu.serial_no[0]);
359         }
360         printf("Images:\n");
361     }
362 /* 22.7 begin */
363     else        /* verbose==0 */
364 #endif /* !__MSDOS__ */
365     {
366         if (*(unsigned short *) buffer == DC_MAGIC)
367             printf("Default boot command line: \"%s\"\n",buffer+2);
368     }
369 /* 22.7 end */
370     for (image = 0; image < MAX_IMAGES; image++) {
371         if (*(name = descrs.d.descr[image].name)) {
372 #if __MSDOS__
373             printf("%s\n", name
374 #else /* !__MSDOS__ */
375             printf("%s%-" SA(MAX_IMAGE_NAME) "s %s%s%s",verbose > 0 ? "  " : "",name,
376               image ? "" : "*",
377 #ifdef LCF_VIRTUAL
378               descrs.d.descr[image].flags & FLAG_VMDEFAULT ? "@" :
379 #endif
380               "",
381 #ifdef LCF_NOKEYBOARD
382               descrs.d.descr[image].flags & FLAG_NOKBDEFAULT ? "&" :
383 #endif
384               ""
385 #endif /* !__MSDOS__ */
386               );
387 #if !__MSDOS__
388             if (verbose >= 2) {
389                 if (descrs.d.descr[image].start.device & (LINEAR_FLAG|LBA32_FLAG)) {
390                    unsigned int sector;
391                    sector = (descrs.d.descr[image].start.device & LBA32_FLAG)
392                       && (descrs.d.descr[image].start.device & LBA32_NOCOUNT)
393                         ? descrs.d.descr[image].start.num_sect : 0;
394                    sector = (sector<<8)+descrs.d.descr[image].start.head;
395                    sector = (sector<<8)+descrs.d.descr[image].start.track;
396                    sector = (sector<<8)+descrs.d.descr[image].start.sector;
397                    printf(" <dev=0x%02x,%s=%d>",
398                      descrs.d.descr[image].start.device&DEV_MASK,
399                      descrs.d.descr[image].start.device&LBA32_FLAG ? "lba32" : "linear",
400                      sector);
401                 }
402                 else { /*  CHS addressing */
403                     printf(" <dev=0x%02x,hd=%d,cyl=%d,sct=%d>",
404                       descrs.d.descr[image].start.device,
405                       descrs.d.descr[image].start.head,
406                       descrs.d.descr[image].start.track,
407                       descrs.d.descr[image].start.sector);
408                 }
409             }
410             printf("\n");
411             if (verbose >= 1) {
412                 flags = descrs.d.descr[image].flags;
413 #ifdef LCF_VIRTUAL
414                 if (flags & FLAG_VMDISABLE)
415                     printf("    Virtual Boot is disabled\n");
416                 if (flags & FLAG_VMWARN)
417                     printf("    Warn on Virtual boot\n");
418 #endif          
419 #ifdef LCF_NOKEYBOARD
420                 if (flags & FLAG_NOKBDISABLE)
421                     printf("    NoKeyboard Boot is disabled\n");
422 #endif          
423                 if ( !(flags & FLAG_PASSWORD) )
424                     printf("    No password\n");
425                 else printf("    Password is required for %s\n",flags &
426                       FLAG_RESTR ? "specifying options" : "booting this image");
427                 printf("    Boot command-line %s be locked\n",flags &
428                   FLAG_LOCK ? "WILL" : "won't");
429                 printf("    %single-key activation\n",flags & FLAG_SINGLE ?
430                   "S" : "No s");
431                 if (flags & FLAG_KERNEL) {
432 #ifdef NORMAL_VGA
433                     if (!(flags & FLAG_VGA))
434                        printf("    VGA mode is taken from boot image\n");
435                     else {
436                         printf("    VGA mode: ");
437                         switch (descrs.d.descr[image].vga_mode) {
438                             case NORMAL_VGA:
439                                 printf("NORMAL\n");
440                                 break;
441                             case EXTENDED_VGA:
442                                 printf("EXTENDED\n");
443                                 break;
444                             case ASK_VGA:
445                                 printf("ASK\n");
446                                 break;
447                             default:
448                                 printf("%d (0x%04x)\n",
449                                   descrs.d.descr[image].vga_mode,
450                                   descrs.d.descr[image].vga_mode);
451                         }
452                     }
453 #endif
454                     if (!(flags & FLAG_LOADHI))
455                         printf("    Kernel is loaded \"low\"\n");
456                     else printf("    Kernel is loaded \"high\"\n");
457                     if (!*(unsigned int *) descrs.d.descr[image].rd_size)
458                         printf("    No initial RAM disk\n");
459                     else printf("    Initial RAM disk is %d bytes\n",
460                           *(unsigned int *) descrs.d.descr[image].rd_size);
461                     if (flags & FLAG_TOOBIG)
462                         printf("       and is too big to fit between 4M-15M\n");
463                 }
464                 if (!geo_find(&geo,descrs.d.descr[image].start)) {
465                     printf("    Map sector not found\n");
466                     continue;
467                 }
468                 if (read(fd,addr,4*sizeof(SECTOR_ADDR)) !=
469                   4*sizeof(SECTOR_ADDR))
470                         die("Read on map file failed (access conflict ?) 2");
471                 if (!geo_find(&geo,addr[0]))
472                     printf("    Fallback sector not found\n");
473                 else {
474                     if (read(fd,buffer,SECTOR_SIZE) != SECTOR_SIZE)
475                         die("Read on map file failed (access conflict ?) 3");
476                     if (*(unsigned short *) buffer != DC_MAGIC)
477                         printf("    No fallback\n");
478                     else printf("    Fallback: \"%s\"\n",buffer+2);
479                 }
480 #define OTHER 0
481 #if OTHER
482                 if (flags & FLAG_KERNEL)
483 #endif
484                     if (!geo_find(&geo,addr[1]))
485                         printf("    Options sector not found\n");
486                     else {
487                         if (read(fd,buffer,SECTOR_SIZE) != SECTOR_SIZE)
488                             die("Read on map file failed (access conflict ?) 4");
489                         if (*buffer) printf("    Options: \"%s\"\n",buffer);
490                         else printf("    No options\n");
491                     }
492 #if OTHER
493                 else {
494 #else
495                 if (!(flags & FLAG_KERNEL)) {
496 #endif
497                     if (geo_find(&geo,addr[3])) show_other(fd);
498                     else printf("    Image data not found\n");
499                 }
500             }
501 #endif /*  !__MSDOS__ */
502         } /* if */
503     } /* for */
504 #undef OTHER
505     (void) close(fd);
506 #if !__MSDOS__
507     if (descrs.l.checksum ==
508           crc32(descrs.sector, sizeof(descrs.l.sector), CRC_POLY1) )
509 #endif /* !__MSDOS__ */
510                 exit(0);
511 #if !__MSDOS__
512     fflush(stdout);
513     fprintf(errstd,"Checksum error\n");
514     exit(1);
515 #endif /* !__MSDOS__ */
516 }
517
518
519 static void usage(char *name)
520 {
521     char *here;
522
523 #if !__MSDOS__
524     here = strrchr(name,'/');
525 #else /* __MSDOS__ */
526     here = strrchr(name,'\\');
527 #endif /* __MSDOS__ */
528     if (here) name = here+1;
529     fprintf(errstd,"usage: %s [ -C config_file ] -q [ -m map_file ] "
530       "[ -v N | -v ... ]\n",name);
531 #if !__MSDOS__
532     fprintf(errstd,"%7s%s [ -C config_file ] [ -b boot_device ] [ -c ] "
533       "[ -g | -l | -L ]\n","",name);
534     fprintf(errstd,"%12s[ -F ] [ -i boot_loader ] [ -m map_file ] [ -d delay ]\n","");
535     fprintf(errstd,"%12s[ -v N | -v ... ] [ -t ] [ -s save_file | -S save_file ]\n",
536       "");
537     fprintf(errstd,"%12s[ -p ][ -P fix | -P ignore ] [ -r root_dir ] [ -w | -w+ ]\n","");
538 #endif /* !__MSDOS__ */
539     fprintf(errstd,"%7s%s [ -C config_file ] [ -m map_file ] "
540       "-R [ word ... ]\n","",name);
541 #if !__MSDOS__
542     fprintf(errstd,"%7s%s [ -C config_file ] -I name [ options ]\n","",name);
543     fprintf(errstd,"%7s%s [ -C config_file ] [ -s save_file ] "
544       "-u | -U [ boot_device ]\n","",name);
545     fprintf(errstd,"%7s%s -H\t\t\t\tinstall only to active discs (RAID-1)\n", "", name);
546     fprintf(errstd,"%7s%s -A /dev/XXX [ N ]\t\tinquire/activate a partition\n","",name);
547     fprintf(errstd,"%7s%s -M /dev/XXX [ mbr | ext ]\tinstall master boot record\n","",name);
548     fprintf(errstd,"%7s%s -T help \t\t\tlist additional options\n", "", name);
549     fprintf(errstd,"%7s%s -X\t\t\t\tinternal compile-time options\n", "", name);
550 #endif /* !__MSDOS__ */
551     fprintf(errstd,"%7s%s -V [ -v ]\t\t\tversion information\n\n","",name);
552     exit(1);
553 }
554
555
556 int main(int argc,char **argv)
557 {
558     char *name,*reboot_arg,*ident_opt,*new_root;
559     char *tell_param, *uninst_dev, *param, *act1, *act2, ch;
560 static char *bitmap_file;
561     int more,version,uninstall,validate,activate,instmbr,geom;
562     int fd, temp=0, tell_early=0;
563     int raid_offset;
564 #if !__MSDOS__
565     struct stat st;
566 #endif /* !__MSDOS__ */
567
568     errstd = stderr;
569 #if VERSION_MINOR>=50
570     if (sizeof(MENUTABLE)!=256) die("MENUTABLE is not 256 bytes (common.h)");
571 #if !__MSDOS__
572     cfg_alpha_check();
573 #endif /* !__MSDOS__ */
574 #endif
575     config_file = DFL_CONFIG;
576     act1 = act2 = tell_param = 
577             reboot_arg = identify = ident_opt = new_root = uninst_dev = NULL;
578     do_md_install = zflag =
579             version = uninstall = validate = activate = instmbr = 0;
580     verbose = -1;
581 #if !__MSDOS__
582     name = *argv;
583 #else  /* __MSDOS__ */
584     name = "lilo";
585 #endif /* __MSDOS__ */
586     argc--;
587
588 #if !__MSDOS__    
589     if (atexit( (void(*)(void)) sync)) die("atexit(sync)");
590     if (atexit( (void(*)(void)) purge)) die("atexit(purge)");
591 #endif /* !__MSDOS__ */
592     
593     cfg_init(cf_options);
594     while (argc && **++argv == '-') {
595         argc--;
596       /* first those options with a mandatory parameter */
597       /* Notably absent are "RuUvw" */
598         if (strchr("AbBCdDEfiImMPrsSTxZ", ch=(*argv)[1])) {
599             if ((*argv)[2]) param = (*argv)+2;
600             else {
601                 param = *++argv;
602                 if(argc-- <= 0) usage(name);
603             }
604         } else { 
605             param = NULL;
606             if (strchr("cFglLpqtVXz", ch)       /* those with no args */
607                 && (*argv)[2]) usage(name);
608         }
609 #if 0
610 fprintf(errstd,"argc=%d, *argv=%s, ch=%c param=%s\n", argc, *argv, ch, param);
611 #endif
612         switch (ch) {
613 #if !__MSDOS__
614             case 'A':
615                 activate = 1;
616                 act1 = param;
617                 if (argc && argv[1][0] != '-') {
618                     act2 = *++argv;
619                     argc--;
620                 }
621                 break;
622             case 'b':
623                 cfg_set(cf_options,"boot",param,NULL);
624                 break;
625             case 'B':
626                 cfg_set(cf_options,"bitmap",param,NULL);
627                 break;
628             case 'c':
629                 cfg_set(cf_options,"compact",NULL,NULL);
630                 compact = 1;
631                 break;
632 #endif /* !__MSDOS */
633             case 'C':
634                 config_file = param;
635                 break;
636 #if !__MSDOS__
637             case 'd':
638                 cfg_set(cf_options,"delay",param,NULL);
639                 break;
640             case 'D':
641                 cfg_set(cf_options,"default",param,NULL);
642                 break;
643             case 'E':
644                 eflag=1;
645                 bitmap_file = param;
646                 break;
647             case 'f':
648                 cfg_set(cf_options,"disktab",param,NULL);
649                 break;
650             case 'F':
651                 force_fs=1;
652                 break;
653             case 'g':
654                 geometric |= AD_GEOMETRIC;
655                 break;
656             case 'H':
657                 force_raid=1;
658                 break;
659             case 'i':
660                 cfg_set(cf_options,"install",param,NULL);
661                 break;
662             case 'I':
663                 identify = param;
664                 if (argc && *argv[1] != '-') {
665                     ident_opt = *++argv;
666                     argc--;
667                 } else {
668                     ident_opt = "i";
669                 }
670                 break;
671             case 'l':
672                 geometric |= AD_LINEAR;
673                 break;
674             case 'L':
675                 geometric |= AD_LBA32;
676                 break;
677 #endif /* !__MSDOS__ */
678             case 'm':
679                 cfg_set(cf_options,"map",param,NULL);
680                 break;
681 #if !__MSDOS__
682             case 'M':
683                 instmbr = 1;
684                 act1 = param;
685 #if !defined LCF_BUILTIN        || 1
686                 if (argc && argv[1][0] != '-') {
687                     act2 = *++argv;
688                     argc--;
689                 }
690 #endif
691                 break;
692             case 'p':
693                 passw = 1;      /* force re-gen of password file */
694                 break;
695             case 'P':
696                 if ((act1=strchr(param,'='))) {
697                     *act1++ = 0;        /* null terminate */
698                     cfg_set(cf_options,param,act1,NULL);
699                 }
700                 else if (!strcasecmp(param,"fix"))
701                     cfg_set(cf_options,"fix-table",NULL,NULL);
702                 else if (!strcasecmp(param,"ignore"))
703                     cfg_set(cf_options,"ignore-table",NULL,NULL);
704                 else if (!strcasecmp(param,"x"))
705                     extended_pt = 1;
706                 else
707                     cfg_set(cf_options,param,NULL,NULL);
708                 break;
709 #endif /* !__MSDOS__ */
710             case 'q':
711                 query = 1;
712                 break;
713 #if !__MSDOS__
714             case 'r':
715                 new_root = param;
716                 break;
717 #endif /* !__MSDOS__ */
718             case 'R':
719                 if (*(param = (*argv)+2)) argc++;
720                 else if (argc) param = *++argv;
721                 else reboot_arg = "";
722                 
723                 while (argc) {
724                         if (!reboot_arg)
725                             *(reboot_arg = alloc(strlen(param)+1)) = 0;
726                         else {
727                             param = *++argv;
728                             strcat(reboot_arg = ralloc(reboot_arg,
729                                 strlen(reboot_arg)+strlen(param)+2)," ");
730                         }
731                         strcat(reboot_arg, param);
732                         argc--;
733                     }
734 #if 0
735 fprintf(errstd,"REBOOT=\"%s\"\n", reboot_arg);              
736 #endif
737                 break;
738 #if !__MSDOS__
739             case 's':
740                 cfg_set(cf_options,"backup",param,NULL);
741                 break;
742             case 'S':
743                 cfg_set(cf_options,"force-backup",param,NULL);
744                 break;
745             case 't':
746                 test = 1;
747                 break;
748             case 'T':
749                 tell_param = param;
750                 break;
751             case 'u':
752                 validate = 1;
753                 /* fall through */
754             case 'U':   /* argument to -u or -U is optional */
755                 uninstall = 1;
756                 if ((*argv)[2]) param = (*argv)+2;
757                 else if (argc && argv[1][0] != '-') {
758                     param = *++argv;
759                     argc--;
760                 }
761                 uninst_dev = param;
762                 break;
763 #endif /* !__MSDOS__ */
764             case 'v':
765                 if ((*argv)[2]) param = (*argv)+2;
766                 else if (argc && argv[1][0]>='0' && argv[1][0]<='9') {
767                     param = *++argv;
768                     argc--;
769                 }
770                 if (param) 
771                     verbose = to_number(param);
772                 else
773                     if (verbose<0) verbose = 1;
774                     else verbose++;
775                 if (verbose) errstd = stdout;
776                 break;
777             case 'V':
778                 version = 1;
779                 break;
780 #if !__MSDOS__
781             case 'w':
782                 cfg_set(cf_options,"nowarn",NULL,NULL);
783                 nowarn = 1;
784                 if ( (*argv)[2] == '+' ) nowarn = -1;
785                 break;
786             case 'x':
787                 cfg_set(cf_options,RAID_EXTRA_BOOT,param,NULL);
788                 break;
789 #endif /* !__MSDOS__ */
790             case 'X':
791                 configuration();
792                 exit(0);
793 #if !__MSDOS__
794             case 'z':
795                 zflag++;        /* force zero of MBR 8-byte area */
796                 break;
797             case 'Z':
798                 cfg_set(cf_options,"bios-passes-dl",param,NULL);
799                 break;
800 #endif /* !__MSDOS__ */
801             default:
802                 usage(name);
803         }
804     }
805     if (argc) usage(name);
806 #if !__MSDOS__
807     if (!new_root) new_root = getenv("ROOT");
808     if (new_root && *new_root) {
809         pp_fd = fopen(PARTITIONS, "r");
810         if (chroot(new_root) < 0) die("chroot %s: %s",new_root,strerror(errno));
811         if (chdir("/dev") < 0)
812                 warn("root at %s has no /dev directory", new_root);
813         if (chdir("/") < 0) die("chdir /: %s",strerror(errno));
814     }
815     if (atexit(temp_remove)) die("atexit() failed");
816     if (version+activate+instmbr+(tell_param!=NULL) > 1) usage(name);
817     if (activate) do_activate(act1, act2);
818 #endif /* !__MSDOS__ */
819
820     if (verbose > 0 || version) {
821         printf("LILO version %d.%d%s", VERSION_MAJOR, VERSION_MINOR, VERSION_EDIT);
822         if (test)
823           printf(" (test mode)\n");
824         else
825           printf(" (released %s)\n", VERSION_DATE);
826         if (version && verbose<=0) {
827           /* exit if user asks for version and no verbose */
828           return 0;
829         }
830         printf("  * Copyright (C) 1992-1998 Werner Almesberger  (until v20)\n"
831                "  * Copyright (C) 1999-2007 John Coffman  (until v22)\n"
832                "  * Copyright (C) 2009-2011 Joachim Wiedorn  (since v23)\n"
833                "This program comes with ABSOLUTELY NO WARRANTY. This is free software \n"
834                "distributed under the BSD License (3-clause). Details can be found in \n"
835                "the file COPYING, which is distributed with this software.\n"
836         );
837         if (verbose>0) {
838 #if !__MSDOS__
839 #include <sys/utsname.h>
840           struct utsname buf;
841 #endif
842           printf("Compiled at %s on %s%s\n", __TIME__, __DATE__, semi);
843 #if !__MSDOS__
844           if (verbose>=2 && uname(&buf)==0) {
845             printf("Running %s kernel %s on %s\n",
846               buf.sysname, buf.release, buf.machine);
847           }
848 #endif
849         }
850         printf("\n");
851         if (version) {
852             if (verbose>=2) configuration();
853             return 0;
854         }
855     }
856
857     if (verbose > 0) errstd = stdout;
858 #if !__MSDOS__
859     preload_types();
860     if (geometric & (geometric-1))
861         die ("Only one of '-g', '-l', or '-L' may be specified");
862
863     if (tell_param) tell_early = strcasecmp(tell_param, "chrul")
864                                 && strcasecmp(tell_param, "ebda");
865     if (eflag) do_bitmap_edit(bitmap_file);
866     if (tell_param && tell_early) probe_tell(tell_param);
867     if (instmbr) do_install_mbr(act1, act2);
868 #endif /* !__MSDOS__ */    
869
870     fd = cfg_open(config_file);
871     more = fd<0 ? 0 : cfg_parse(cf_options);
872     
873 #if !__MSDOS__
874     temp = cfg_get_flag(cf_options,"nowarn");
875     if (nowarn < 0) nowarn = 0;
876     else nowarn = temp;
877 /* All warnings appear if very verbose modes used */
878     if (verbose>=3) nowarn = 0;
879 #endif /* !__MSDOS__ */
880
881     if (verbose>=6) printf("main: cfg_parse returns %d\n", more);
882
883 #if !__MSDOS__
884     if (tell_param && !tell_early) probe_tell(tell_param);
885
886     if (fstat(fd,&st) < 0)
887             die("fstat %s: %s", config_file, strerror(errno) );
888
889     if (S_ISREG(st.st_mode)) {
890         if (st.st_uid)
891             warn("%s should be owned by root", config_file);
892         else if (st.st_mode & (S_IWGRP | S_IWOTH))
893             warn("%s should be writable only for root", config_file);
894         config_read = !!(st.st_mode & (S_IRGRP | S_IROTH));
895     }
896
897     if (!cfg_get_flag(cf_options,"nodevcache"))  preload_dev_cache();
898     
899     if (verbose<0 && cfg_get_strg(cf_options,"verbose"))
900         verbose = to_number(cfg_get_strg(cf_options,"verbose"));
901     if (verbose<0) verbose = 0;
902     if (verbose) errstd = stdout;
903
904     compact = cfg_get_flag(cf_options,"compact");
905     geom = cfg_get_flag(cf_options,"geometric");
906     linear = cfg_get_flag(cf_options,"linear");
907     lba32  = cfg_get_flag(cf_options,"lba32");
908     
909     if (geom+linear+lba32 > 1)
910         die("May specify only one of GEOMETRIC, LINEAR or LBA32");
911     if (geometric) {
912         if (geom+linear+lba32 > 0)  
913             warn("Ignoring entry '%s'", geom ? "geometric" :
914                       linear ? "linear" : "lba32");
915         geom = linear = lba32 = 0;
916         if (geometric==AD_LBA32) lba32 = 1;
917         else if (geometric==AD_LINEAR) linear = 1;
918         else if (geometric==AD_GEOMETRIC) geom = 1;
919     }    
920     if (geom+linear+lba32 == 0) {
921         warn("LBA32 addressing assumed");
922         lba32 = 1;
923     }
924     if (linear) warn(
925         "LINEAR is deprecated in favor of LBA32:  LINEAR specifies 24-bit\n"
926         "  disk addresses below the 1024 cylinder limit; LBA32 specifies 32-bit disk\n"
927         "  addresses not subject to cylinder limits on systems with EDD-BIOS extensions;\n"
928         "  use LINEAR only if you are aware of its limitations.");
929     
930     if (identify) identify_image(identify,ident_opt);
931
932     if (uninstall)
933         bsect_uninstall(uninst_dev ? uninst_dev : cfg_get_strg(cf_options,
934               "boot"),cfg_get_strg(cf_options,"backup"),validate);
935 #endif /* !__MSDOS__ */
936
937     if (reboot_arg) {
938         map_patch_first(cfg_get_strg(cf_options,"map") ? cfg_get_strg(
939               cf_options,"map") : MAP_FILE, reboot_arg);
940         exit(0);
941     }
942
943 #if !__MSDOS__
944     if ( (param = cfg_get_strg(cf_options,"bios-passes-dl")) ) {
945         if (strchr("YyTt1", *param)) bios_passes_dl = DL_GOOD;
946         if (strchr("NnFf0", *param)) bios_passes_dl = DL_BAD;
947     }
948     if (bios_passes_dl == DL_NOT_SET)   check_bios();   /* in probe.c */
949
950     if (compact && (linear || lba32) && verbose>=4)
951         warn("COMPACT may conflict with %s on some "
952                 "systems", lba32 ? "LBA32" : "LINEAR");
953
954     geo_init(cfg_get_strg(cf_options,"disktab"));
955 #endif /* !__MSDOS__ */
956     if (query)
957         show_images(!cfg_get_strg(cf_options,"map") ? MAP_FILE :
958               cfg_get_strg(cf_options,"map"));
959
960 #if !__MSDOS__
961 /*************************************************/
962 /*  Doing a real install (may be test mode)      */
963 /*************************************************/
964
965 /* test for a RAID installation */
966         raid_offset = raid_setup();
967         if (verbose >= 2) {
968             printf("raid_setup returns offset = %08X  ndisk = %d\n", raid_offset, ndisk);
969             dump_serial_nos();    
970         }
971
972         if (verbose >=2 && do_md_install)
973             printf("raid flags: at bsect_open  0x%02X\n", raid_flags);
974
975         bsect_open(
976                 cfg_get_strg(cf_options,"boot"),
977                 cfg_get_strg(cf_options,"map") ?
978                         cfg_get_strg(cf_options,"map") : MAP_FILE,
979                 cfg_get_strg(cf_options,"install"),
980                 cfg_get_strg(cf_options,"delay") ?
981                         timer_number(cfg_get_strg(cf_options,"delay")) : 0,
982                 cfg_get_strg(cf_options,"timeout") ?
983                         timer_number(cfg_get_strg(cf_options,"timeout")) : -1,
984                 raid_offset );
985         if (more) {
986             cfg_init(cf_top);
987             if (cfg_parse(cf_top)) cfg_error("Syntax error");
988         }
989         
990         temp = bsect_number();
991         if (temp==0) die("No images have been defined.");
992         else if (temp<0) die("Default image doesn't exist.");
993
994 #ifdef LCF_VIRTUAL
995         check_vmdefault();
996 #endif
997 #ifdef LCF_NOKEYBOARD
998         check_nokbdefault();
999 #endif
1000         check_fallback();
1001         check_unattended();
1002         
1003         if (verbose>=2) dump_serial_nos();
1004         if (do_md_install) raid_final();
1005         else if (!test) {
1006             char *cp;
1007             
1008             if (verbose) printf("Writing boot sector.\n");
1009
1010             cp = cfg_get_strg(cf_options,"force-backup");
1011             if (cp) bsect_update(cp,1,0);
1012             else bsect_update(cfg_get_strg(cf_options,"backup"),0,0);
1013
1014         } 
1015         else {
1016             bsect_cancel();
1017             if (passw)
1018                 printf("The password crc file has *NOT* been updated.\n");
1019
1020             printf("The boot sector and the map file have *NOT* been "
1021               "altered.\n");
1022         }
1023         if (verbose>=4) dump_serial_nos();
1024         if (warnings) {
1025             if (warnings>1)
1026                 printf("%d warnings were ", warnings);
1027             else printf("One warning was ");
1028             printf("%sed.\n", nowarn ? "suppress" : "issu");
1029         }
1030 #else  /* __MSDOS__ */
1031         die("No option switches specified:  -q, -R, or -V");
1032 #endif /* __MSDOS__ */
1033         
1034     return 0;
1035 }