123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 |
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <sys/stat.h>
- #include <sys/types.h>
- #include "system.h"
- #include <disklabel.h>
- #include <config.h>
- #include "library.h"
- #define SECT_SIZE 512
- #define BOOT_SECTOR 2
- int read_configured_partition(int disk_fd, char* buf)
- {
- u_int64_t bootsize, bootsect, bootpart = 0;
- long *p = (long *) buf;
-
- if(lseek(disk_fd,60*8,SEEK_SET)<0) {
- perror("lseek on disk");
- exit(1);
- }
- /* Find old configuration */
- read(disk_fd, &bootsize, sizeof(bootsize));
- read(disk_fd, &bootsect, sizeof(bootsect));
- if(lseek(disk_fd,SECT_SIZE*bootsect,SEEK_SET)<0)
- return 0; /* probably random garbage in the boot block - not
- a fatal error */
- read(disk_fd, buf, SECT_SIZE);
- while ((char *)p < buf + SECT_SIZE)
- if (*p++ == ABOOT_MAGIC)
- bootpart = *p;
- return bootpart;
- }
- int main(int argc, char **argv)
- {
- u_int64_t bootsize,kernelsize=0;
- u_int64_t bootsect=BOOT_SECTOR;
- u_int64_t magicnum=0;
- int disk_fd,file_fd,kernel_fd=0;
- struct disklabel dlabel;
- struct stat s;
- int x;
- char buf[2048];
- int c;
- int err=0, part, bootpart=0;
- unsigned force_overlap=0;
- int verbose=0;
- extern int optind;
- extern char *optarg;
- char *bootfile=0, *device=0, *kernel=0;
-
- while ((c=getopt(argc,argv,"f:c:v?"))!=EOF)
- switch(c)
- {
- case '?':
- err=1;
- break;
- case 'f':
- part = atoi(optarg);
- if (part < 1 || part > 8) {
- fprintf(stderr, "%s: partition number must be in range 1-8\n",
- argv[0]);
- exit(1);
- }
- force_overlap |= 1U << (part - 1);
- break;
- case 'c':
- bootpart = atoi(optarg);
- if (bootpart < 1 || bootpart > 8) {
- fprintf(stderr, "%s: partition number must be in range 1-8\n",
- argv[0]);
- exit(1);
- }
- break;
- case 'v':
- verbose=1;
- break;
- default:
- err=1;
- break;
- }
- if(optind<argc)
- device=argv[optind++];
- if(optind<argc)
- bootfile=argv[optind++];
- if(optind<argc)
- kernel=argv[optind++];
-
- if(!bootfile || !device || err)
- {
- fprintf(stderr, "Usage: %s [-f[1-8]] [-c[1-8]] [-v] disk bootfile [kernel]\n",
- argv[0]);
- exit(1);
- }
-
- disk_fd=open(device,O_RDWR);
- file_fd=open(bootfile,O_RDONLY);
- if(disk_fd<0) {
- perror("open disk device");
- exit(1);
- }
- if(file_fd<0) {
- perror("open bootfile");
- exit(1);
- }
-
- if(kernel)
- {
- kernel_fd=open(kernel,O_RDONLY);
- if (kernel_fd<0)
- {
- perror("open kernel");
- exit(1);
- }
- else
- {
- if(fstat(kernel_fd,&s)) {
- perror("fstat kernel");
- exit(1);
- }
- kernelsize=(s.st_size+SECT_SIZE-1)/SECT_SIZE;
- }
- }
- if(read_disklabel(disk_fd,&dlabel)) {
- fprintf(stderr,"Couldn't get a valid disk label, exiting\n");
- exit(1);
- }
- if(fstat(file_fd,&s)) {
- perror("fstat bootfile");
- exit(1);
- }
- bootsize=(s.st_size+SECT_SIZE-1)/SECT_SIZE;
- if(-1 !=(x=overlaplabel(&dlabel,bootsect,bootsize+bootsect+kernelsize,force_overlap)))
- {
- fprintf(stderr,
- "error: bootcode overlaps with partition #%d. "
- "If you really want this, use -f%d\n",
- x + 1, x + 1);
- exit(1);
- }
- if(!bootpart) {
- bootpart = read_configured_partition(disk_fd, buf);
- if (verbose) {
- if (bootpart) {
- printf("preserving boot partition %d\n", bootpart);
- } else {
- printf("could not find existing aboot, configuring for second partition\n");
- }
- }
- } else {
- if (verbose) {
- printf("setting boot partition to %d\n", bootpart);
- }
- }
- if(lseek(disk_fd,60*8,SEEK_SET)<0) {
- perror("lseek on disk");
- exit(1);
- }
- write(disk_fd,&bootsize,sizeof(bootsize));
- write(disk_fd,&bootsect,sizeof(bootsect));
- write(disk_fd,&magicnum,sizeof(magicnum));
- if (verbose)
- {
- fprintf(stderr,"bootsize:%lu sectors\n",bootsize);
- fprintf(stderr,"bootsect:%lu\n",bootsect);
- }
- if(lseek(disk_fd,SECT_SIZE*bootsect,SEEK_SET)<0) {
- perror("lseek #3 on disk\n");
- exit(1);
- }
- while((x=read(file_fd,buf,2048))>0) {
- write(disk_fd,buf,x);
- }
- close(file_fd);
- if (kernel_fd > 0 && kernelsize>0)
- {
- unsigned long len = 0;
- if (verbose)
- fprintf(stderr,"kernel:%lu sectors\n",kernelsize);
- #if 0
- if(lseek(disk,BOOT_SIZE+BOOT_SECTOR*SECT_SIZE,SEEK_SET)<0) {
- perror("lseek #4 on disk\n");
- exit(1);
- }
- #endif
- while((x=read(kernel_fd,buf,2048))>0)
- {
- write(disk_fd,buf,x);
- len += x;
- }
- close(kernel_fd);
- if ((len+SECT_SIZE-1)/SECT_SIZE != kernelsize)
- fprintf(stderr,"warning: kernel read %lu, should be %lu\n",(len+SECT_SIZE-1)/SECT_SIZE,kernelsize);
- }
- /* Now write the aboot partition config if we had one */
- if (bootpart) {
- long *p = (long *) buf;
- if(lseek(disk_fd,SECT_SIZE*bootsect,SEEK_SET)<0) {
- perror("lseek #5 on disk\n");
- exit(1);
- }
- read(disk_fd, buf, SECT_SIZE);
- while ((char *)p < buf + SECT_SIZE) {
- if (*p++ == ABOOT_MAGIC) {
- *p = bootpart;
- }
- }
- lseek(disk_fd,SECT_SIZE*bootsect,SEEK_SET);
- write(disk_fd, buf, SECT_SIZE);
- }
- dosumlabel(disk_fd,&dlabel);
- close(disk_fd);
- if(verbose)
- fprintf(stderr,"done!\n");
- return 0;
- }
|