dec-multia: make netboot possible, add aboot bootloader
[openadk.git] / package / aboot / src / tools / isomarkboot.c
blobba01009fa9d8d4510d36b94796f7c7dc05976f9f
1 /*
2 * isomarkboot.c
4 * This file is part of aboot, the SRM bootloader for Linux/Alpha
5 * Copyright (C) 1996 David Mosberger.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of the
10 * License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 * Making an ISO9660 filesystem bootable is straight-forward since all
23 * files are contiguous.
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
30 #include <asm/fcntl.h>
32 #include <config.h>
33 #include <isolib.h>
34 #include <iso.h>
36 const char * prog_name;
38 static int disk;
40 void
41 __memcpy (void * dest, const void * src, size_t n)
43 memcpy (dest, src, n);
46 long
47 iso_dev_read (void * buf, long offset, long size)
49 if (lseek(disk, offset, SEEK_SET) != offset) {
50 perror("lseek");
51 return -1;
53 return read(disk, buf, size);
56 /* Write a 64-bit quantity out into memory in LITTLE ENDIAN order */
57 static void write_64 (unsigned char* out, unsigned long long in)
59 out[0] = in & 0xFF;
60 out[1] = (in >> 8) & 0xFF;
61 out[2] = (in >> 16) & 0xFF;
62 out[3] = (in >> 24) & 0xFF;
63 out[4] = (in >> 32) & 0xFF;
64 out[5] = (in >> 40) & 0xFF;
65 out[6] = (in >> 48) & 0xFF;
66 out[7] = (in >> 56) & 0xFF;
69 /* Read in a 64-bit LITTLE ENDIAN quantity */
70 static unsigned long long read_64 (unsigned char *in)
72 unsigned long long result = 0;
74 result |= (unsigned long long) in[0];
75 result |= (unsigned long long) in[1] << 8;
76 result |= (unsigned long long) in[2] << 16;
77 result |= (unsigned long long) in[3] << 24;
78 result |= (unsigned long long) in[4] << 32;
79 result |= (unsigned long long) in[5] << 40;
80 result |= (unsigned long long) in[6] << 48;
81 result |= (unsigned long long) in[7] << 56;
83 return result;
86 int
87 main (int argc, char ** argv)
89 u_int64_t sector[512 / 8], sum;
90 struct iso_primary_descriptor vol_desc;
91 size_t nbytes, aboot_size;
92 off_t aboot_pos;
93 int i, aboot_fd;
94 int rootbin_fd;
95 off_t rootbin_pos;
96 char root_start[100];
98 prog_name = argv[0];
100 if (argc < 3 || argc > 4) {
101 fprintf(stderr, "usage: %s filesys path [root.bin]\n", prog_name);
102 exit(1);
104 disk = open(argv[1], O_RDWR);
105 if (disk < 0) {
106 perror(argv[1]);
107 exit(1);
110 if (iso_read_super (0, 0) < 0) {
111 fprintf(stderr, "%s: cannot mount\n", argv[1]);
112 exit(1);
115 aboot_fd = iso_open(argv[2]);
116 if (aboot_fd < 0) {
117 fprintf(stderr, "%s: file not found\n", argv[2]);
118 exit(1);
122 struct stat buf;
123 iso_fstat(aboot_fd, &buf);
124 aboot_size = buf.st_size;
127 aboot_pos = iso_map (aboot_fd, 0);
129 printf("%s: %s is at offset %ld and is %lu bytes long\n",
130 prog_name, argv[2], aboot_pos, aboot_size);
132 if (lseek(disk, 0, SEEK_SET) != 0) {
133 perror("lseek");
134 return -1;
137 nbytes = read(disk, sector, sizeof(sector));
138 if (nbytes != sizeof(sector)) {
139 if ((long) nbytes < 0) {
140 perror("read");
141 } else {
142 fprintf(stderr, "%s: short read\n", prog_name);
144 exit(1);
147 strcpy((char *) sector, "Linux/Alpha aboot for ISO filesystem.");
148 write_64 ((unsigned char *) &sector[60], aboot_size / 512);/* sector count */
149 write_64 ((unsigned char *) &sector[61], aboot_pos / 512); /* starting LBM */
150 write_64 ((unsigned char *) &sector[62], 0); /* flags */
152 /* update checksum: */
153 sum = 0;
154 for (i = 0; i < 63; i++)
155 sum += read_64 ((unsigned char *) &sector[i]);
157 write_64 ((unsigned char *) &sector[63], sum);
159 if (lseek(disk, 0, SEEK_SET) != 0) {
160 perror("lseek");
161 return -1;
164 nbytes = write(disk, sector, sizeof(sector));
165 if (nbytes != sizeof(sector)) {
166 if ((long) nbytes < 0) {
167 perror("write");
168 } else {
169 fprintf(stderr, "%s: short write\n", prog_name);
171 exit(1);
174 if (argc < 4)
175 return 0;
177 rootbin_fd = iso_open(argv[3]);
178 if (rootbin_fd < 0) {
179 fprintf(stderr, "%s: file not found\n", argv[3]);
180 exit(1);
183 rootbin_pos = iso_map (rootbin_fd, 0);
184 iso_close(rootbin_fd);
187 struct stat buf;
188 iso_fstat(rootbin_fd, &buf);
189 printf("%s: %s is at offset %ld and is %lu bytes long\n",
190 prog_name, argv[3], rootbin_pos, buf.st_size);
194 if (lseek(disk, 16*2048, SEEK_SET) != 16*2048) {
195 perror("lseek");
196 return -1;
198 nbytes = read(disk, &vol_desc, sizeof(vol_desc));
199 if (nbytes != sizeof(vol_desc)) {
200 if ((long) nbytes < 0) {
201 perror("read");
202 } else {
203 fprintf(stderr, "%s: short read\n", prog_name);
205 exit(1);
208 if (strncmp (vol_desc.id, ISO_STANDARD_ID, sizeof vol_desc.id) != 0) {
209 fprintf(stderr,"first volume descriptor has not an ISO_STANDARD_ID!!\n");
210 exit(1);
212 if (isonum_711 (vol_desc.type) != ISO_VD_PRIMARY) {
213 fprintf(stderr,"first volume descriptor is not a primary one!!\n");
214 exit(1);
216 if (rootbin_pos & 2047) {
217 fprintf(stderr,"erreur:rootbin_pos=%ld is not at a isoblock boundary\n",rootbin_pos);
218 exit(1);
220 sprintf(root_start,"ROOT START=%ld ",rootbin_pos/2048);
221 printf("writing %s in application_data of first volume descriptor\n", root_start);
222 memcpy(vol_desc.application_data,root_start,strlen(root_start));
223 if (lseek(disk, 16*2048, SEEK_SET) != 16*2048) {
224 perror("lseek");
225 return -1;
228 nbytes = write(disk, &vol_desc, sizeof(vol_desc));
229 if (nbytes != sizeof(vol_desc)) {
230 if ((long) nbytes < 0) {
231 perror("write");
232 } else {
233 fprintf(stderr, "%s: short write\n", prog_name);
235 exit(1);
238 return 0;