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.
30 #include <asm/fcntl.h>
36 const char * prog_name
;
41 __memcpy (void * dest
, const void * src
, size_t n
)
43 memcpy (dest
, src
, n
);
47 iso_dev_read (void * buf
, long offset
, long size
)
49 if (lseek(disk
, offset
, SEEK_SET
) != offset
) {
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
)
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;
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
;
100 if (argc
< 3 || argc
> 4) {
101 fprintf(stderr
, "usage: %s filesys path [root.bin]\n", prog_name
);
104 disk
= open(argv
[1], O_RDWR
);
110 if (iso_read_super (0, 0) < 0) {
111 fprintf(stderr
, "%s: cannot mount\n", argv
[1]);
115 aboot_fd
= iso_open(argv
[2]);
117 fprintf(stderr
, "%s: file not found\n", argv
[2]);
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) {
137 nbytes
= read(disk
, sector
, sizeof(sector
));
138 if (nbytes
!= sizeof(sector
)) {
139 if ((long) nbytes
< 0) {
142 fprintf(stderr
, "%s: short read\n", prog_name
);
147 strcpy((char *) sector
, "Linux/Alpha aboot for ISO filesystem.");
148 write_64 ((unsigned char *) §or
[60], aboot_size
/ 512);/* sector count */
149 write_64 ((unsigned char *) §or
[61], aboot_pos
/ 512); /* starting LBM */
150 write_64 ((unsigned char *) §or
[62], 0); /* flags */
152 /* update checksum: */
154 for (i
= 0; i
< 63; i
++)
155 sum
+= read_64 ((unsigned char *) §or
[i
]);
157 write_64 ((unsigned char *) §or
[63], sum
);
159 if (lseek(disk
, 0, SEEK_SET
) != 0) {
164 nbytes
= write(disk
, sector
, sizeof(sector
));
165 if (nbytes
!= sizeof(sector
)) {
166 if ((long) nbytes
< 0) {
169 fprintf(stderr
, "%s: short write\n", prog_name
);
177 rootbin_fd
= iso_open(argv
[3]);
178 if (rootbin_fd
< 0) {
179 fprintf(stderr
, "%s: file not found\n", argv
[3]);
183 rootbin_pos
= iso_map (rootbin_fd
, 0);
184 iso_close(rootbin_fd
);
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) {
198 nbytes
= read(disk
, &vol_desc
, sizeof(vol_desc
));
199 if (nbytes
!= sizeof(vol_desc
)) {
200 if ((long) nbytes
< 0) {
203 fprintf(stderr
, "%s: short read\n", prog_name
);
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");
212 if (isonum_711 (vol_desc
.type
) != ISO_VD_PRIMARY
) {
213 fprintf(stderr
,"first volume descriptor is not a primary one!!\n");
216 if (rootbin_pos
& 2047) {
217 fprintf(stderr
,"erreur:rootbin_pos=%ld is not at a isoblock boundary\n",rootbin_pos
);
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) {
228 nbytes
= write(disk
, &vol_desc
, sizeof(vol_desc
));
229 if (nbytes
!= sizeof(vol_desc
)) {
230 if ((long) nbytes
< 0) {
233 fprintf(stderr
, "%s: short write\n", prog_name
);