diff options
author | Waldemar Brodkorb <wbx@openadk.org> | 2017-12-31 18:47:16 +0100 |
---|---|---|
committer | Waldemar Brodkorb <wbx@openadk.org> | 2017-12-31 18:47:25 +0100 |
commit | 3a96085b999220c4da0c5ef7d1f7ba26b9ddfb98 (patch) | |
tree | 77f1445aae2e6be5135594e95986b3278bbc061c /package/aboot/src/tools/isomarkboot.c | |
parent | cc28479164b8dc8afd4310716da32f16022f5974 (diff) |
dec-multia: make netboot possible, add aboot bootloader
Diffstat (limited to 'package/aboot/src/tools/isomarkboot.c')
-rw-r--r-- | package/aboot/src/tools/isomarkboot.c | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/package/aboot/src/tools/isomarkboot.c b/package/aboot/src/tools/isomarkboot.c new file mode 100644 index 000000000..ba01009fa --- /dev/null +++ b/package/aboot/src/tools/isomarkboot.c @@ -0,0 +1,239 @@ +/* + * isomarkboot.c + * + * This file is part of aboot, the SRM bootloader for Linux/Alpha + * Copyright (C) 1996 David Mosberger. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * Making an ISO9660 filesystem bootable is straight-forward since all + * files are contiguous. + */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <asm/fcntl.h> + +#include <config.h> +#include <isolib.h> +#include <iso.h> + +const char * prog_name; + +static int disk; + +void +__memcpy (void * dest, const void * src, size_t n) +{ + memcpy (dest, src, n); +} + +long +iso_dev_read (void * buf, long offset, long size) +{ + if (lseek(disk, offset, SEEK_SET) != offset) { + perror("lseek"); + return -1; + } + return read(disk, buf, size); +} + +/* Write a 64-bit quantity out into memory in LITTLE ENDIAN order */ +static void write_64 (unsigned char* out, unsigned long long in) +{ + out[0] = in & 0xFF; + out[1] = (in >> 8) & 0xFF; + out[2] = (in >> 16) & 0xFF; + out[3] = (in >> 24) & 0xFF; + out[4] = (in >> 32) & 0xFF; + out[5] = (in >> 40) & 0xFF; + out[6] = (in >> 48) & 0xFF; + out[7] = (in >> 56) & 0xFF; +} + +/* Read in a 64-bit LITTLE ENDIAN quantity */ +static unsigned long long read_64 (unsigned char *in) +{ + unsigned long long result = 0; + + result |= (unsigned long long) in[0]; + result |= (unsigned long long) in[1] << 8; + result |= (unsigned long long) in[2] << 16; + result |= (unsigned long long) in[3] << 24; + result |= (unsigned long long) in[4] << 32; + result |= (unsigned long long) in[5] << 40; + result |= (unsigned long long) in[6] << 48; + result |= (unsigned long long) in[7] << 56; + + return result; +} + +int +main (int argc, char ** argv) +{ + u_int64_t sector[512 / 8], sum; + struct iso_primary_descriptor vol_desc; + size_t nbytes, aboot_size; + off_t aboot_pos; + int i, aboot_fd; + int rootbin_fd; + off_t rootbin_pos; + char root_start[100]; + + prog_name = argv[0]; + + if (argc < 3 || argc > 4) { + fprintf(stderr, "usage: %s filesys path [root.bin]\n", prog_name); + exit(1); + } + disk = open(argv[1], O_RDWR); + if (disk < 0) { + perror(argv[1]); + exit(1); + } + + if (iso_read_super (0, 0) < 0) { + fprintf(stderr, "%s: cannot mount\n", argv[1]); + exit(1); + } + + aboot_fd = iso_open(argv[2]); + if (aboot_fd < 0) { + fprintf(stderr, "%s: file not found\n", argv[2]); + exit(1); + } + + { + struct stat buf; + iso_fstat(aboot_fd, &buf); + aboot_size = buf.st_size; + } + + aboot_pos = iso_map (aboot_fd, 0); + + printf("%s: %s is at offset %ld and is %lu bytes long\n", + prog_name, argv[2], aboot_pos, aboot_size); + + if (lseek(disk, 0, SEEK_SET) != 0) { + perror("lseek"); + return -1; + } + + nbytes = read(disk, sector, sizeof(sector)); + if (nbytes != sizeof(sector)) { + if ((long) nbytes < 0) { + perror("read"); + } else { + fprintf(stderr, "%s: short read\n", prog_name); + } + exit(1); + } + + strcpy((char *) sector, "Linux/Alpha aboot for ISO filesystem."); + write_64 ((unsigned char *) §or[60], aboot_size / 512);/* sector count */ + write_64 ((unsigned char *) §or[61], aboot_pos / 512); /* starting LBM */ + write_64 ((unsigned char *) §or[62], 0); /* flags */ + + /* update checksum: */ + sum = 0; + for (i = 0; i < 63; i++) + sum += read_64 ((unsigned char *) §or[i]); + + write_64 ((unsigned char *) §or[63], sum); + + if (lseek(disk, 0, SEEK_SET) != 0) { + perror("lseek"); + return -1; + } + + nbytes = write(disk, sector, sizeof(sector)); + if (nbytes != sizeof(sector)) { + if ((long) nbytes < 0) { + perror("write"); + } else { + fprintf(stderr, "%s: short write\n", prog_name); + } + exit(1); + } + + if (argc < 4) + return 0; + + rootbin_fd = iso_open(argv[3]); + if (rootbin_fd < 0) { + fprintf(stderr, "%s: file not found\n", argv[3]); + exit(1); + } + + rootbin_pos = iso_map (rootbin_fd, 0); + iso_close(rootbin_fd); + + { + struct stat buf; + iso_fstat(rootbin_fd, &buf); + printf("%s: %s is at offset %ld and is %lu bytes long\n", + prog_name, argv[3], rootbin_pos, buf.st_size); + } + + + if (lseek(disk, 16*2048, SEEK_SET) != 16*2048) { + perror("lseek"); + return -1; + } + nbytes = read(disk, &vol_desc, sizeof(vol_desc)); + if (nbytes != sizeof(vol_desc)) { + if ((long) nbytes < 0) { + perror("read"); + } else { + fprintf(stderr, "%s: short read\n", prog_name); + } + exit(1); + } + + if (strncmp (vol_desc.id, ISO_STANDARD_ID, sizeof vol_desc.id) != 0) { + fprintf(stderr,"first volume descriptor has not an ISO_STANDARD_ID!!\n"); + exit(1); + } + if (isonum_711 (vol_desc.type) != ISO_VD_PRIMARY) { + fprintf(stderr,"first volume descriptor is not a primary one!!\n"); + exit(1); + } + if (rootbin_pos & 2047) { + fprintf(stderr,"erreur:rootbin_pos=%ld is not at a isoblock boundary\n",rootbin_pos); + exit(1); + } + sprintf(root_start,"ROOT START=%ld ",rootbin_pos/2048); + printf("writing %s in application_data of first volume descriptor\n", root_start); + memcpy(vol_desc.application_data,root_start,strlen(root_start)); + if (lseek(disk, 16*2048, SEEK_SET) != 16*2048) { + perror("lseek"); + return -1; + } + + nbytes = write(disk, &vol_desc, sizeof(vol_desc)); + if (nbytes != sizeof(vol_desc)) { + if ((long) nbytes < 0) { + perror("write"); + } else { + fprintf(stderr, "%s: short write\n", prog_name); + } + exit(1); + } + + return 0; +} |