source: grub-pc/trunk/fuentes/debian/grub-extras/ntldr-img/grubinst.c @ 22

Last change on this file since 22 was 22, checked in by mabarracus, 4 years ago

updated version and apply net.ifnames=0 into debian/rules

File size: 29.6 KB
Line 
1/*
2 *  GRUB Utilities --  Utilities for GRUB Legacy, GRUB2 and GRUB for DOS
3 *  Copyright (C) 2007 Bean (bean123@126.com)
4 *
5 *  This program is free software; you can redistribute it and/or modify
6 *  it under the terms of the GNU General Public License as published by
7 *  the Free Software Foundation; either version 2 of the License, or
8 *  (at your option) any later version.
9 *
10 *  This program is distributed in the hope that it will be useful,
11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 *  GNU General Public License for more details.
14 *
15 *  You should have received a copy of the GNU General Public License
16 *  along with this program; if not, write to the Free Software
17 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <fcntl.h>
24#include <sys/stat.h>
25#include <errno.h>
26#include <unistd.h>
27
28#ifndef WIN32
29
30#define O_BINARY                0
31
32#endif
33
34#include "grub_mbr.h"
35#include "utils.h"
36#include "version.h"
37
38// Application flags, used by this program
39
40#define AFG_VERBOSE             1
41#define AFG_PAUSE               2
42#define AFG_READ_ONLY           4
43#define AFG_NO_BACKUP_MBR       8
44#define AFG_FORCE_BACKUP_MBR    16
45#define AFG_RESTORE_PREVMBR     32
46#define AFG_LIST_PART           64
47#define AFG_IS_FLOPPY           128
48#define AFG_LBA_MODE            256
49#define AFG_CHS_MODE            512
50#define AFG_OUTPUT              1024
51#define AFG_EDIT                2048
52
53// Grldr flags, this flag is used by grldr.mbr
54
55#define GFG_DISABLE_FLOPPY      1
56#define GFG_DISABLE_OSBR        2
57#define GFG_DUCE                4
58#define GFG_PREVMBR_LAST        128
59
60#define APP_NAME                "grubinst: "
61
62#define print_pause             if (afg & AFG_PAUSE) {fputs("Press <ENTER> to continue ...\n",stderr); fflush(stderr); fgetc(stdin);}
63
64#define print_apperr(a)         { fprintf(stderr,APP_NAME "%s\n",a); print_pause; }
65#define print_syserr(a)         { perror(APP_NAME a); print_pause; }
66
67static void help(void)
68{
69  fputs("Usage:\n"
70        "\tgrubinst  [OPTIONS]  DEVICE_OR_FILE\n\n"
71        "OPTIONS:\n\n"
72        "\t--help,-h\t\tShow usage information\n\n"
73        "\t--pause\t\t\tPause before exiting\n\n"
74        "\t--version\t\tShow version information\n\n"
75        "\t--verbose,-v\t\tVerbose output\n\n"
76        "\t--list-part,-l\t\tList all logical partitions in DEVICE_OR_FILE\n\n"
77        "\t--save=FN,-s=FN\t\tSave the orginal MBR/BS to FN\n\n"
78        "\t--restore=FN,-r=FN\tRestore MBR/BS from previously saved FN\n\n"
79        "\t--restore-prevmbr,-r\tRestore previous MBR saved in the second sector\n"
80        "\t\t\t\tof DEVICE_OR_FILE\n\n"
81        "\t--read-only,-t\t\tdo everything except the actual write to the\n"
82        "\t\t\t\tspecified DEVICE_OR_FILE. (test mode)\n\n"
83        "\t--no-backup-mbr\t\tdo not copy the old MBR to the second sector of\n"
84        "\t\t\t\tDEVICE_OR_FILE.\n\n"
85        "\t--force-backup-mbr\tforce the copy of old MBR to the second sector\n"
86        "\t\t\t\tof DEVICE_OR_FILE.(default)\n\n"
87        "\t--mbr-enable-floppy\tenable the search for GRLDR on floppy.(default)\n\n"
88        "\t--mbr-disable-floppy\tdisable the search for GRLDR on floppy.\n\n"
89        "\t--mbr-enable-osbr\tenable the boot of PREVIOUS MBR with invalid\n"
90        "\t\t\t\tpartition table (usually an OS boot sector).\n"
91        "\t\t\t\t(default)\n\n"
92        "\t--mbr-disable-osbr\tdisable the boot of PREVIOUS MBR with invalid\n"
93        "\t\t\t\tpartition table (usually an OS boot sector).\n\n"
94        "\t--duce\t\t\tdisable the feature of unconditional entrance\n"
95        "\t\t\t\tto the command-line.\n\n"
96        "\t--boot-prevmbr-first\ttry to boot PREVIOUS MBR before the search for\n"
97        "\t\t\t\tGRLDR.\n\n"
98        "\t--boot-prevmbr-last\ttry to boot PREVIOUS MBR after the search for\n"
99        "\t\t\t\tGRLDR.(default)\n\n"
100        "\t--preferred-drive=D\tpreferred boot drive number, 0 <= D < 255.\n\n"
101        "\t--preferred-partition=P\tpreferred partition number, 0 <= P < 255.\n\n"
102        "\t--time-out=T,-t=T\twait T seconds before booting PREVIOUS MBR. if\n"
103        "\t\t\t\tT is 0xff, wait forever. The default is 5.\n\n"
104        "\t\t\t\tbefore booting PREVIOUS MBR. K is a word\n"
105        "\t\t\t\tvalue, just as the value in AX register\n"
106        "\t\t\t\treturned from int16/AH=1. The high byte is the\n"
107        "\t\t\t\tscan code and the low byte is ASCII code. The\n"
108        "\t\t\t\tdefault is 0x3920 for space bar.\n\n"
109        "\t--key-name=S\t\tSpecify the name of the hot key.\n\n"
110        "\t--floppy,-f\t\tif DEVICE_OR_FILE is floppy, use this option.\n\n"
111        "\t--floppy=N\t\tif DEVICE_OR_FILE is a partition on a hard\n"
112        "\t\t\t\tdrive, use this option. N is used to specify\n"
113        "\t\t\t\tthe partition number: 0,1,2 and 3 for the\n"
114        "\t\t\t\tprimary partitions, and 4,5,6,... for the\n"
115        "\t\t\t\tlogical partitions.\n\n"
116        "\t--sectors-per-track=S\tspecifies sectors per track for --floppy.\n"
117        "\t\t\t\t1 <= S <= 63, default is 63.\n\n"
118        "\t--heads=H\t\tspecifies number of heads for --floppy.\n"
119        "\t\t\t\t1 <= H <= 256, default is 255.\n\n"
120        "\t--start-sector=B\tspecifies hidden sectors for --floppy=N.\n\n"
121        "\t--total-sectors=C\tspecifies total sectors for --floppy.\n"
122        "\t\t\t\tdefault is 0.\n\n"
123        "\t--lba\t\t\tuse lba mode for --floppy. If the floppy BIOS\n"
124        "\t\t\t\thas LBA support, you can specify --lba here.\n"
125        "\t\t\t\tIt is assumed that all floppy BIOSes have CHS\n"
126        "\t\t\t\tsupport. So you would rather specify --chs.\n"
127        "\t\t\t\tIf neither --chs nor --lba is specified, then\n"
128        "\t\t\t\tthe LBA indicator(i.e., the third byte of the\n"
129        "\t\t\t\tboot sector) will not be touched.\n\n"
130        "\t--chs\t\t\tuse chs mode for --floppy. You should specify\n"
131        "\t\t\t\t--chs if the floppy BIOS does not support LBA.\n"
132        "\t\t\t\tWe assume all floppy BIOSes have CHS support.\n"
133        "\t\t\t\tSo it is likely you want to specify --chs.\n"
134        "\t\t\t\tIf neither --chs nor --lba is specified, then\n"
135        "\t\t\t\tthe LBA indicator(i.e., the third byte of the\n"
136        "\t\t\t\tboot sector) will not be touched.\n\n"
137        "\t--install-partition=I\tInstall the boot record onto the boot area of\n"
138        "\t-p=I\t\t\tpartition number I of the specified hard drive\n"
139        "\t\t\t\tor harddrive image DEVICE_OR_FILE.\n\n"
140        "\t--boot-file=F,-b=F\tChange the name of boot file.\n\n"
141        "\t--load-seg=S\t\tChange load segment for boot file.\n\n"
142        "\t--grub2,-2\t\tLoad grub2 kernel g2ldr instead of grldr.\n\n"
143        "\t--output,-o\t\tSave embeded grldr.mbr to DEVICE_OR_FILE.\n\n"
144        "\t--edit,-e\t\tEdit external grldr/grldr.mbr.\n",
145        stderr);
146}
147
148int afg,gfg,def_drive,def_part,time_out,hot_key,part_num;
149int def_spt,def_hds,def_ssc,def_tsc;
150char *save_fn,*restore_fn,boot_file_83[12];
151const char *key_name;
152const char *boot_file;
153unsigned short load_seg;
154
155static char fn_buf[24];
156
157static char* get_disk_name(int n)
158{
159#if defined(WIN32)
160  sprintf(fn_buf,"\\\\.\\PhysicalDrive%d",n);
161#elif defined(LINUX)
162  sprintf(fn_buf,"/dev/hd%c",'a'+n);
163#elif defined(FREEBSD)
164  sprintf(fn_buf,"/dev/ad%d",n);
165#else
166  print_apperr("Disk device is not supported in your system");
167  return NULL;
168#endif
169  return fn_buf;
170}
171
172static char* get_flop_name(int n)
173{
174#if defined(WIN32)
175  if (n>1)
176    {
177      print_apperr("Only two floppy drives are supported");
178      return NULL;
179    }
180  sprintf(fn_buf,"\\\\.\\%c:",'A'+n);
181#elif defined(LINUX) || defined(FREEBSD)
182  sprintf(fn_buf,"/dev/fd%d",n);
183#else
184  print_apperr("Floppy device is not supported in your system");
185  return NULL;
186#endif
187  return fn_buf;
188}
189
190static char* parse_fname(char* fn)
191{
192  if ((afg & AFG_OUTPUT) && (fn[0]=='('))
193    {
194      print_apperr("Can\'t use device name while using --output option");
195      return NULL;
196    }
197  if ((! strncmp(fn,"(hd",3)) || (! strncmp(fn,"(fd",3)))
198    {
199      int n;
200      char *p;
201
202      n=strtol(&fn[3],&p,0);
203      if ((n<0) || (n>=MAX_DISKS))
204        {
205          print_apperr("Invalid device number");
206          return NULL;
207        }
208      if (*p==',')
209        {
210          part_num=strtol(p+1,&p,0);
211          if ((part_num<0) || (part_num>=MAX_PARTS))
212            {
213              print_apperr("Invalid partition number");
214              return NULL;
215            }
216        }
217      if ((*p!=')') || (*(p+1)!=0))
218        {
219          print_apperr("Invalid device name");
220          return NULL;
221        }
222      if (fn[1]=='h')
223        fn=get_disk_name(n);
224      else
225        {
226          fn=get_flop_name(n);
227          afg|=AFG_IS_FLOPPY;
228        }
229    }
230  return fn;
231}
232
233static char* str_upcase(char* str)
234{
235  int i;
236
237  for (i=0;str[i];i++)
238    if ((str[i]>='a') && (str[i]<='z'))
239      str[i]-='a'-'A';
240
241  return str;
242}
243
244static char* str_lowcase(char* str)
245{
246  int i;
247
248  for (i=0;str[i];i++)
249    if ((str[i]>='A') && (str[i]<='Z'))
250      str[i]+='a'-'A';
251
252  return str;
253}
254
255static int SetBootFile(char* fn)
256{
257  char* pc;
258
259  if (*fn==0)
260    return 1;
261  if (strlen(fn)>7)
262    return 1;
263  pc=strchr(fn,'.');
264  if (pc)
265    if ((pc==fn) || (pc-fn>8) || (strlen(pc+1)>3))
266      return 1;
267  str_upcase(fn);
268  memset(boot_file_83,' ',sizeof(boot_file_83)-1);
269  if (pc)
270    {
271      memcpy(boot_file_83,fn,pc-fn);
272      memcpy(&boot_file_83[8],pc+1,strlen(pc+1));
273    }
274  else
275    memcpy(boot_file_83,fn,strlen(fn));
276  str_lowcase(fn);
277  boot_file=fn;
278  return 0;
279}
280
281static void list(int hd)
282{
283  xde_t xe;
284
285  xe.cur=xe.nxt=0xFF;
286  fprintf(stderr," #  id        base        leng\n");
287  while (! xd_enum(hd,&xe))
288    fprintf(stderr,"%2d  %02llX    %8llX    %8llX\n",xe.cur,
289            (unsigned long long) xe.dfs,
290            (unsigned long long) xe.bse,
291            (unsigned long long) xe.len);
292}
293
294static int is_grldr_mbr(unsigned char* buf)
295{
296  int i,n;
297
298  i=0x1B7;
299  n=sizeof("Missing MBR-helper.")-1;
300
301  while ((i>n) && (buf[i]==0))
302    i--;
303  return (! memcmp(&buf[i-n+1],"Missing MBR-helper.", sizeof("Missing MBR-helper.")));
304}
305
306static int install(char* fn)
307{
308  int hd = -1,nn,fs,slen;
309  unsigned char prev_mbr[sizeof(grub_mbr)];
310  unsigned long ssec;
311
312  if (fn==NULL)
313    return 1;
314
315  if (afg & AFG_EDIT)
316    {
317      unsigned short r1,r2;
318
319      if (afg & AFG_VERBOSE)
320        fprintf(stderr,"Edit mode\n");
321      hd=open(fn,O_RDWR | O_BINARY,0644);
322      if (hd==-1)
323        {
324          print_syserr("open");
325          return errno;
326        }
327      r1=get16(&grub_mbr[0x1FFA],0);
328      nn=read(hd,grub_mbr,sizeof(grub_mbr));
329      if (nn==-1)
330        {
331          print_syserr("read");
332          close(hd);
333          return errno;
334        }
335      if (nn<(int)sizeof(grub_mbr))
336        {
337          print_apperr("The input file is too short");
338          close(hd);
339          return 1;
340        }
341      if (get32(&grub_mbr[0x1FFC],0)!=0xAA555247)
342        {
343          print_apperr("Invalid input file");
344          close(hd);
345          return 1;
346        }
347      r2=get16(&grub_mbr[0x1FFA],0);
348      if (r1!=r2)
349        {
350          char buf[80];
351
352          sprintf(buf,"Version number mismatched (old=%d new=%d)",r2,r1);
353          print_apperr(buf);
354          close(hd);
355          return 1;
356        }
357      go_sect(hd,0);
358      afg |= AFG_OUTPUT;
359    }
360
361  if (boot_file)
362    {
363      unsigned short ofs;
364
365      // Patching the FAT32 boot sector
366      ofs=get16(&grub_mbr,0x400+0x1EC) & 0x7FF;
367      strcpy((char *) &grub_mbr[0x400+ofs],boot_file_83);
368      if (load_seg)
369        set16(&grub_mbr,0x400+0x1EA,load_seg);
370
371      // Patching the FAT12/FAT16 boot sector
372      ofs=get16(&grub_mbr,0x600+0x1EC) & 0x7FF;
373      strcpy((char *) &grub_mbr[0x600+ofs],boot_file_83);
374      if (load_seg)
375        set16(&grub_mbr,0x600+0x1EA,load_seg);
376
377      // Patching the EXT2 boot sector
378      ofs=get16(grub_mbr,0x800+0x1EE) & 0x7FF;
379      strcpy((char *) &grub_mbr[0x800+ofs],boot_file);
380
381      // Patching the NTFS sector
382      ofs=get16(grub_mbr,0xA00+0x1EC) & 0x7FF;
383      strcpy((char *) &grub_mbr[0xA00+ofs],boot_file);
384      if (load_seg)
385        set16(grub_mbr,0xA00+0x1EA,load_seg);
386
387      if (afg & AFG_VERBOSE)
388        {
389          fprintf(stderr,"Boot file changed to %s\n",boot_file);
390          if (load_seg)
391            fprintf(stderr,"Load segment changed to %04X\n",load_seg);
392        }
393    }
394
395  if (afg & AFG_OUTPUT)
396    {
397      int mode;
398
399      mode=(! (afg & AFG_READ_ONLY))?(O_TRUNC | O_CREAT):0;
400      if (! (afg & AFG_EDIT))
401        {
402          if (afg & AFG_VERBOSE)
403            fprintf(stderr,"Extract mode\n");
404          hd=open(fn,O_RDWR | O_BINARY | mode,0644);
405          if (hd==-1)
406            {
407              print_syserr("open");
408              return errno;
409            }
410        }
411      if (! (afg & AFG_READ_ONLY))
412        if (write(hd,grub_mbr,sizeof(grub_mbr))!=sizeof(grub_mbr))
413          {
414            print_apperr("Write to output file fails");
415            close(hd);
416            return 1;
417          }
418      goto quit;
419    }
420
421  memset(&grub_mbr[512],0,512);
422  grub_mbr[2] = gfg;
423  grub_mbr[3]=time_out;
424  set16(&grub_mbr,4,hot_key);
425  grub_mbr[6] = def_drive;
426  grub_mbr[7] = def_part;
427  if ((key_name==NULL) && (hot_key==0x3920))
428    key_name="SPACE";
429  if (key_name)
430    strcpy((char *) &grub_mbr[0x1fec],key_name);
431
432  hd=open(fn,O_RDWR | O_BINARY,S_IREAD | S_IWRITE);
433  if (hd==-1)
434    {
435      print_syserr("open");
436      return errno;
437    }
438  if (afg & AFG_LIST_PART)
439    {
440      list(hd);
441      close(hd);
442      return 0;
443    }
444  if (part_num!=-1)
445    {
446      if (def_ssc!=-1)
447        ssec=def_ssc;
448      else
449        {
450          xde_t xe;
451
452          xe.cur=0xFF;
453          xe.nxt=part_num;
454          if (xd_enum(hd,&xe))
455            {
456              print_apperr("Partition not found");
457              close(hd);
458              return 1;
459            }
460          ssec=xe.bse;
461          if (afg & AFG_VERBOSE)
462            fprintf(stderr,"Part Fs: %02X (%s)\nPart Leng: %llu\n",xe.dfs,dfs2str(xe.dfs),
463                    (unsigned long long) xe.len);
464        }
465    }
466  else
467    ssec=0;
468  if (afg & AFG_VERBOSE)
469    fprintf(stderr,"Start sector: %llu\n", (unsigned long long) ssec);
470  if ((ssec) && (go_sect(hd,ssec)))
471    {
472      print_apperr("Can\'t seek to the start sector");
473      close(hd);
474      return 1;
475    }
476  nn=read(hd,prev_mbr,sizeof(prev_mbr));
477  if (nn==-1)
478    {
479      print_syserr("read");
480      close(hd);
481      return errno;
482    }
483  if (nn<(int)sizeof(prev_mbr))
484    {
485      print_apperr("The input file is too short");
486      close(hd);
487      return 1;
488    }
489  fs=get_fstype(prev_mbr);
490  if (afg & AFG_VERBOSE)
491    {
492      fprintf(stderr,"Image type: %s\n",fst2str(fs));
493      if (fs==FST_MBR)
494        fprintf(stderr,"Num of heads: %d\nSectors per track: %d\n",mbr_nhd,mbr_spt);
495    }
496  if (fs==FST_OTHER)
497    {
498      print_apperr("Unknown image type");
499      close(hd);
500      return 1;
501    }
502  if (((part_num!=-1) || (afg & AFG_IS_FLOPPY)) && (fs==FST_MBR))
503    {
504      print_apperr("Should be a file system image");
505      close(hd);
506      return 1;
507    }
508  if ((part_num==-1) && ((afg & AFG_IS_FLOPPY)==0) && (fs!=FST_MBR))
509    {
510      print_apperr("Should be a disk image");
511      close(hd);
512      return 1;
513    }
514  if (fs==FST_MBR)
515    {
516      int n,nfs,sln;
517      unsigned long ofs;
518      unsigned char bs[1024];
519
520      ofs=0xFFFFFFFF;
521      for (n=0x1BE;n<0x1FE;n+=16)
522        if (prev_mbr[n+4])
523          {
524            if (ofs>get32(&prev_mbr[n],8))
525              ofs=get32(&prev_mbr[n],8);
526          }
527      if (ofs<(sizeof(prev_mbr)>>9))
528        {
529          print_apperr("Not enough room to install mbr");
530          close(hd);
531          return 1;
532        }
533      slen=sizeof(prev_mbr);
534      if (go_sect(hd,ofs))
535        {
536          print_apperr("Can\'t seek to the first partition");
537          close(hd);
538          return 1;
539        }
540      if (read(hd,bs,sizeof(bs))!=sizeof(bs))
541        {
542          print_apperr("Fail to read boot sector");
543          close(hd);
544          return 1;
545        }
546      nfs=get_fstype(bs);
547      if (nfs==FST_FAT32)
548        sln=0x5A - 0xB;
549      else if (nfs==FST_FAT16)
550        sln=0x3E - 0xB;
551      else
552        sln=0;
553      if (sln)
554        {
555          memcpy(&grub_mbr[0xB],&bs[0xB],sln);
556          set32(&grub_mbr[0],0x1C,0);
557          set16(&grub_mbr[0],0xE,get16(&grub_mbr[0],0xE) + ofs);
558        }
559    }
560  else if (fs==FST_NTFS)
561    slen=2048;
562  else
563    slen=512;
564
565  if (go_sect(hd,ssec))
566    {
567      print_apperr("Can\'t seek to the start sector");
568      close(hd);
569      return 1;
570    }
571
572  if (save_fn)
573    {
574      int h2;
575
576      h2=open(save_fn,O_CREAT | O_TRUNC | O_RDWR | O_BINARY,S_IREAD | S_IWRITE);
577      if (h2==-1)
578        {
579          print_syserr("open save file");
580          close(hd);
581          return errno;
582        }
583      nn=write(h2,prev_mbr,slen);
584      if (nn==-1)
585        {
586          print_syserr("write save file");
587          close(hd);
588          close(h2);
589          return errno;
590        }
591      if (nn<slen)
592        {
593          print_apperr("Can\'t write the whole MBR to the save file");
594          close(hd);
595          close(h2);
596          return 1;
597        }
598      close(h2);
599    }
600  if (afg & AFG_RESTORE_PREVMBR)
601    {
602      if (fs!=FST_MBR)
603        {
604          print_apperr("Not a disk image");
605          close(hd);
606          return 1;
607        }
608      if (memcmp(&prev_mbr[1024+3],"GRLDR",5))
609        {
610          print_apperr("GRLDR is not installed");
611          close(hd);
612          return 1;
613        }
614      if (get16(prev_mbr,512+510)!=0xAA55)
615        {
616          print_apperr("No previous saved MBR");
617          close(hd);
618          return 1;
619        }
620      memset(&grub_mbr,0,sizeof(grub_mbr));
621      memcpy(&grub_mbr,&prev_mbr[512],512);
622      memcpy(&grub_mbr[0x1b8],&prev_mbr[0x1b8],72);
623
624      if (afg & AFG_VERBOSE)
625        fprintf(stderr,"Restore previous MBR mode\n");
626    }
627  else
628    {
629      // Load MBR/BS from restore file or configure grub_mbr
630      if (restore_fn)
631        {
632          int h2;
633
634          h2=open(restore_fn,O_RDONLY | O_BINARY,S_IREAD);
635          if (h2==-1)
636            {
637              print_syserr("open restore file");
638              close(hd);
639              return errno;
640            }
641          nn=read(h2,grub_mbr,slen);
642          if (nn==-1)
643            {
644              print_syserr("read restore file");
645              close(hd);
646              close(h2);
647              return errno;
648            }
649          if ((nn<512) || ((nn & 0x1FF)!=0) ||
650              ((fs!=FST_EXT2) && (get16(grub_mbr,510)!=0xAA55)))
651            {
652              print_apperr("Invalid restore file");
653              close(hd);
654              close(h2);
655              return 1;
656            }
657          close(h2);
658          if (nn<slen)
659            memset(&grub_mbr[nn],0,slen-nn);
660
661          //if ((fs==FST_FAT16) || (fs==FST_FAT32) || (fs==FST_NTFS))
662          if (fs!=FST_EXT2)
663            {
664              int new_fs;
665
666              new_fs=get_fstype(grub_mbr);
667              if (new_fs!=fs)
668                {
669                  print_apperr("Invalid restore file");
670                  close(hd);
671                  return 1;
672                }
673            }
674
675          if (afg & AFG_VERBOSE)
676            fprintf(stderr,"Restore mode\n");
677        }
678      else
679        {
680          if (fs==FST_MBR)
681            {
682              if (! (afg & AFG_NO_BACKUP_MBR))
683                {
684                  int i;
685
686                  if (afg & AFG_FORCE_BACKUP_MBR)
687                    i=512;
688                  else
689                    for (i=1;i<512;i++)
690                      if (prev_mbr[512+i]!=prev_mbr[512])
691                        break;
692
693                  if ((i==512) && (! is_grldr_mbr(prev_mbr)))
694                    memcpy(&grub_mbr[512],prev_mbr,512);
695                  else
696                    memcpy(&grub_mbr[512],&prev_mbr[512],512);
697                }
698              memcpy(&grub_mbr[0x1b8],&prev_mbr[0x1b8],72);
699            }
700          else if (fs==FST_FAT16)
701            {
702              memcpy(grub_mbr,&grub_mbr[0x600],slen);
703              grub_mbr[0x41]=part_num;
704            }
705          else if (fs==FST_FAT32)
706            {
707              memcpy(grub_mbr,&grub_mbr[0x400],slen);
708              grub_mbr[0x5D]=part_num;
709            }
710          else if (fs==FST_NTFS)
711            {
712              memcpy(grub_mbr,&grub_mbr[0xA00],slen);
713              grub_mbr[0x57]=part_num;
714            }
715          else if (fs==FST_EXT2)
716            {
717              memcpy(&grub_mbr,&grub_mbr[0x800],slen);
718              grub_mbr[0x25]=part_num;
719              if (afg & AFG_LBA_MODE)
720                grub_mbr[2]=0x42;
721              else if (afg & AFG_CHS_MODE)
722                grub_mbr[2]=0x2;
723              if (def_spt!=-1)
724                set16(&grub_mbr,0x18,def_spt);
725              else if ((afg & AFG_IS_FLOPPY)==0)
726                set16(&grub_mbr,0x18,63);
727              if (def_hds!=-1)
728                set16(&grub_mbr,0x1A,def_hds);
729              else if ((afg & AFG_IS_FLOPPY)==0)
730                set16(&grub_mbr,0x1A,255);
731              if (def_tsc!=-1)
732                set32(&grub_mbr,0x20,def_tsc);
733              set32(&grub_mbr,0x1C,ssec);
734              // s_inode_size
735              if (prev_mbr[1024+0x4C]) // s_rev_level
736                set16(&grub_mbr,0x26,get16(&prev_mbr[1024],0x58));
737              else
738                set16(&grub_mbr,0x26,0x80);
739              // s_inodes_per_group
740              set32(&grub_mbr,0x28,get32(&prev_mbr[1024],0x28));
741              // s_first_data_block+1
742              set32(&grub_mbr,0x2C,get32(&prev_mbr[1024],0x14)+1);
743            }
744          else
745            {
746              // Shouldn't be here
747              print_apperr("Invalid file system");
748              close(hd);
749              return 1;
750            }
751          if ((fs==FST_FAT16) || (fs==FST_FAT32) || (fs==FST_NTFS))
752            {
753              if (afg & AFG_LBA_MODE)
754                grub_mbr[2]=0xe;
755              else if (afg & AFG_CHS_MODE)
756                grub_mbr[2]=0x90;
757              else
758                grub_mbr[2]=prev_mbr[2];
759            }
760
761          if (afg & AFG_VERBOSE)
762            fprintf(stderr,"Install mode\n");
763        }
764      // Patch the new MBR/BS with information from prev_mbr
765      if (fs==FST_MBR)
766        memcpy(&grub_mbr[0x1b8],&prev_mbr[0x1b8],72);
767      else if (fs==FST_FAT16)
768        {
769          memcpy(&grub_mbr[0xB],&prev_mbr[0xB],0x3E - 0xB);
770          set32(grub_mbr,0x1C,ssec);
771        }
772      else if (fs==FST_FAT32)
773        {
774          memcpy(&grub_mbr[0xB],&prev_mbr[0xB],0x5A - 0xB);
775          set32(grub_mbr,0x1C,ssec);
776        }
777      else if (fs==FST_NTFS)
778        {
779          memcpy(&grub_mbr[0xB],&prev_mbr[0xB],0x54 - 0xB);
780          set32(grub_mbr,0x1C,ssec);
781        }
782    }
783  if (! (afg & AFG_READ_ONLY))
784    {
785      nn=write(hd,grub_mbr,slen);
786      if (nn==-1)
787        {
788          print_syserr("write");
789          close(hd);
790          return errno;
791        }
792      if (nn<slen)
793        {
794          print_apperr("Can\'t write the whole mbr");
795          close(hd);
796          return 1;
797        }
798    }
799  else if (afg & AFG_VERBOSE)
800    fprintf(stderr,"Read only mode\n");
801quit:
802  close(hd);
803  if (afg & AFG_PAUSE)
804    {
805      fputs("The MBR/BS has been successfully installed\n",stderr);
806      print_pause;
807    }
808  return 0;
809}
810
811int main(int argc,char** argv)
812{
813  int idx;
814
815  afg=gfg=0;
816  part_num=def_drive=def_part=def_spt=def_hds=def_ssc=def_tsc=-1;
817  afg=0;
818  gfg=GFG_PREVMBR_LAST;
819  time_out=5;
820  hot_key=0x3920;
821  save_fn=NULL;
822  restore_fn=NULL;
823  for (idx=1;idx<argc;idx++)
824    {
825      if (argv[idx][0]!='-')
826        break;
827      if ((! strcmp(argv[idx],"--help"))
828          || (! strcmp(argv[idx],"-h")))
829        {
830          help();
831          print_pause;
832          return 1;
833        }
834      else if (! strcmp(argv[idx],"--version"))
835        {
836          fprintf(stderr,"grubinst version : " VERSION "\n");
837          print_pause;
838          return 1;
839        }
840      else if ((! strcmp(argv[idx],"--verbose")) ||
841               (! strcmp(argv[idx],"-v")))
842        afg |=AFG_VERBOSE;
843      else if (! strcmp(argv[idx],"--pause"))
844        afg|=AFG_PAUSE;
845      else if ((! strcmp(argv[idx],"--read-only"))
846               || (! strcmp(argv[idx],"-t")))
847        afg|=AFG_READ_ONLY;
848      else if (! strcmp(argv[idx],"--no-backup-mbr"))
849        afg|=AFG_NO_BACKUP_MBR;
850      else if (! strcmp(argv[idx],"--force-backup-mbr"))
851        afg|=AFG_FORCE_BACKUP_MBR;
852      else if (! strcmp(argv[idx],"--mbr-enable-floppy"))
853        gfg&=~GFG_DISABLE_FLOPPY;
854      else if (! strcmp(argv[idx],"--mbr-disable-floppy"))
855        gfg|=GFG_DISABLE_FLOPPY;
856      else if (! strcmp(argv[idx],"--mbr-enable-osbr"))
857        gfg&=~GFG_DISABLE_OSBR;
858      else if (! strcmp(argv[idx],"--mbr-disable-osbr"))
859        gfg|=GFG_DISABLE_OSBR;
860      else if (! strcmp(argv[idx],"--duce"))
861        gfg|=GFG_DUCE;
862      else if (! strcmp(argv[idx],"--boot-prevmbr-first"))
863        gfg&=~GFG_PREVMBR_LAST;
864      else if (! strcmp(argv[idx],"--boot-prevmbr-last"))
865        gfg|=GFG_PREVMBR_LAST;
866      else if (! strncmp(argv[idx],"--preferred-drive=",18))
867        {
868          def_drive=strtol(&argv[idx][18],NULL,0);
869          if ((def_drive<0) || (def_drive>=255))
870            {
871              print_apperr("Invalid preferred drive number");
872              return 1;
873            }
874        }
875      else if (! strncmp(argv[idx],"--preferred-partition=",22))
876        {
877          def_part=strtol(&argv[idx][22],NULL,0);
878          if ((def_part<0) || (def_part>=255))
879            {
880              print_apperr("Invalid preferred partition number");
881              return 1;
882            }
883        }
884      else if ((! strncmp(argv[idx],"--time-out=",11)) ||
885               (! strncmp(argv[idx],"-t=",3)))
886        {
887          time_out=strtol((argv[idx][2]=='=')?&argv[idx][3]:&argv[idx][11],NULL,0);
888          if ((time_out<0) || (time_out>255))
889            {
890              print_apperr("Invalid timeout value");
891              return 1;
892            }
893        }
894      else if ((! strncmp(argv[idx],"--key-name=",11)))
895        {
896          key_name=&argv[idx][11];
897          if (strlen(key_name)>13)
898            {
899              print_apperr("Key name too long");
900              return 1;
901            }
902        }
903      else if ((! strcmp(argv[idx],"--restore-prevmbr")) ||
904               (! strcmp(argv[idx],"-r")))
905        afg|=AFG_RESTORE_PREVMBR;
906      else if ((! strncmp(argv[idx],"--save=",7)) ||
907               (! strncmp(argv[idx],"-s=",3)))
908        {
909          save_fn=(argv[idx][2]=='=')?&argv[idx][3]:&argv[idx][7];
910          if (*save_fn==0)
911            {
912              print_apperr("Empty filename");
913              return 1;
914            }
915        }
916      else if ((! strncmp(argv[idx],"--restore=",10)) ||
917               (! strncmp(argv[idx],"-r=",3)))
918        {
919          restore_fn=(argv[idx][2]=='=')?&argv[idx][3]:&argv[idx][10];
920          if (*restore_fn==0)
921            {
922              print_apperr("Empty filename");
923              return 1;
924            }
925        }
926      else if ((! strcmp(argv[idx],"--list-part")) ||
927               (! strcmp(argv[idx],"-l")))
928        afg|=AFG_LIST_PART;
929      else if ((! strcmp(argv[idx],"--floppy")) ||
930               (! strcmp(argv[idx],"-f")))
931        afg|=AFG_IS_FLOPPY;
932      else if ((! strncmp(argv[idx],"--floppy=",9)) ||
933               (! strncmp(argv[idx],"--install-partition=",20)) ||
934               (! strncmp(argv[idx],"-p=",3)))
935        {
936          char *p;
937
938          if (argv[idx][2]=='f')
939            p=&argv[idx][9];
940          else if (argv[idx][2]=='i')
941            p=&argv[idx][20];
942          else
943            p=&argv[idx][3];
944          part_num=strtoul(p,NULL,0);
945          if ((part_num<0) || (part_num>=MAX_PARTS))
946            {
947              print_apperr("Invalid partition number");
948              return 1;
949            }
950        }
951      else if (! strcmp(argv[idx],"--lba"))
952        afg|=AFG_LBA_MODE;
953      else if (! strcmp(argv[idx],"--chs"))
954        afg|=AFG_CHS_MODE;
955      else if (! strncmp(argv[idx],"--sectors-per-track=",20))
956        {
957          def_spt=strtol(&argv[idx][10],NULL,0);
958          if ((def_spt<1) || (def_spt>63))
959            {
960              print_apperr("Invalid sector per track");
961              return 1;
962            }
963        }
964      else if (! strncmp(argv[idx],"--heads=",8))
965        {
966          def_hds=strtol(&argv[idx][8],NULL,0);
967          if ((def_hds<1) || (def_hds>255))
968            {
969              print_apperr("Invalid number of heads");
970              return 1;
971            }
972        }
973      else if (! strncmp(argv[idx],"--start-sector=",15))
974        {
975          def_spt=strtol(&argv[idx][15],NULL,0);
976          if (def_ssc<0)
977            {
978              print_apperr("Invalid start sector");
979              return 1;
980            }
981        }
982      else if (! strncmp(argv[idx],"--total-sectors=",16))
983        {
984          def_tsc=strtol(&argv[idx][16],NULL,0);
985          if (def_tsc<0)
986            {
987              print_apperr("Invalid total sectors");
988              return 1;
989            }
990        }
991      else if ((! strncmp(argv[idx],"--boot-file=",12)) ||
992               (! strncmp(argv[idx],"-b=",3)))
993        {
994          if (SetBootFile((argv[idx][2]=='=')?&argv[idx][3]:&argv[idx][12]))
995            {
996              print_apperr("Invalid boot file name");
997              return 1;
998            }
999        }
1000      else if (! strncmp(argv[idx],"--load-seg=",11))
1001        {
1002          load_seg=strtoul(&argv[idx][11],NULL,16);
1003          if (load_seg<0x1000)
1004            {
1005              print_apperr("Load address too small");
1006              return 1;
1007            }
1008        }
1009      else if ((! strcmp(argv[idx],"--grub2")) ||
1010               (! strcmp(argv[idx],"-2")))
1011        {
1012          if (! boot_file)
1013            {
1014              boot_file="g2ldr";
1015              strcpy(boot_file_83,"G2LDR      ");
1016            }
1017        }
1018      else if ((! strcmp(argv[idx],"--output")) ||
1019               (! strcmp(argv[idx],"-o")))
1020        afg|=AFG_OUTPUT;
1021      else if ((! strcmp(argv[idx],"--edit")) ||
1022               (! strcmp(argv[idx],"-e")))
1023        afg|=AFG_EDIT;
1024      else
1025        {
1026          print_apperr("Invalid option, please use --help to see all valid options");
1027          return 1;
1028        }
1029    }
1030  if (idx>=argc)
1031    {
1032      print_apperr("No filename specified");
1033      return 1;
1034    }
1035  if (idx<argc-1)
1036    {
1037      print_apperr("Extra parameters");
1038      return 1;
1039    }
1040  return install(parse_fname(argv[idx]));
1041}
Note: See TracBrowser for help on using the repository browser.