summaryrefslogtreecommitdiff
path: root/package/aboot/src/sdisklabel/swriteboot.c
diff options
context:
space:
mode:
authorWaldemar Brodkorb <wbx@openadk.org>2017-12-31 18:47:16 +0100
committerWaldemar Brodkorb <wbx@openadk.org>2017-12-31 18:47:25 +0100
commit3a96085b999220c4da0c5ef7d1f7ba26b9ddfb98 (patch)
tree77f1445aae2e6be5135594e95986b3278bbc061c /package/aboot/src/sdisklabel/swriteboot.c
parentcc28479164b8dc8afd4310716da32f16022f5974 (diff)
dec-multia: make netboot possible, add aboot bootloader
Diffstat (limited to 'package/aboot/src/sdisklabel/swriteboot.c')
-rw-r--r--package/aboot/src/sdisklabel/swriteboot.c226
1 files changed, 226 insertions, 0 deletions
diff --git a/package/aboot/src/sdisklabel/swriteboot.c b/package/aboot/src/sdisklabel/swriteboot.c
new file mode 100644
index 000000000..8c93d4402
--- /dev/null
+++ b/package/aboot/src/sdisklabel/swriteboot.c
@@ -0,0 +1,226 @@
+#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;
+}