/[scripts]/trunk/isobar.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/isobar.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 114 - (show annotations)
Sun May 3 16:35:58 2009 UTC (14 years, 10 months ago) by dpavlin
File MIME type: text/plain
File size: 6424 byte(s)
boot floppy image extractor described at
http://www.thinkwiki.org/wiki/BIOS_update_without_optical_disk

1 /*
2 * isobar.c: ISO Boot Archive Remover.
3 *
4 * Jason Hood, 6, 8 & 9 March, 2005.
5 *
6 * Extract the boot image (or code if no emulation) from a bootable CD-ROM
7 * (or an image of one).
8 *
9 * Adapted from the program by David Brinkman.
10 *
11 * v1.01, 30 May, 2005:
12 * always include Image Size in display.
13 *
14 * v1.02, 5 & 6 June, 2005:
15 * Win32 port.
16 *
17 * v1.03, 10 Nov, 2007:
18 * Linux port by newhren <colimit@gmail.com>
19 *
20 * Todo: possibly replace the boot image in a CD image;
21 * recognise boot sections;
22 * ignore non-bootable CDs (are there any?).
23 *
24 * http://www.phoenix.com/NR/rdonlyres/98D3219C-9CC9-4DF5-B496-A286D893E36A/0/specscdrom.pdf
25 * http://www.geocities.com/jadoxa/shsucdx/omibar32.zip
26 * http://adoxa.110mb.com/shsucdx/omibar32.zip
27 * http://colimit.googlepages.com/isobar.c
28 *
29 */
30
31 #define PVERS "1.03"
32 #define PDATE "10 Nov, 2007"
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <fcntl.h>
38 #include <stdint.h>
39 #include <unistd.h>
40 #include <sys/stat.h>
41
42 typedef uint8_t BYTE;
43 typedef uint16_t WORD;
44 typedef uint32_t DWORD;
45 typedef unsigned int UINT;
46
47 #define MAX 32
48 #define OFLAG O_CREAT | O_WRONLY | O_TRUNC
49 #define OMODE S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH
50
51 char * buf;
52 DWORD offset = 0, imgsize;
53 int fdin;
54
55 int CDRead( UINT SectorCount, DWORD StartSector )
56 {
57 return (pread(fdin, buf, SectorCount << 11, StartSector << 11) == SectorCount << 11); // Sector size = 0x800
58 }
59
60 const char* platform[] = { "80x86",
61 "Power PC",
62 "Mac" };
63
64 const char* boot_type[] = { "no emulation",
65 "1.2 meg floppy",
66 "1.44 meg floppy",
67 "2.88 meg floppy",
68 "hard disk" };
69
70 enum
71 {
72 E_OK, // No problems
73 E_OPT, // Unknown/invalid option
74 E_MEM, // Not enough memory
75 E_NOCD, // Not a CD drive, MSCDEX/SHSUCDX not installed,
76 // unknown CD format or no CD present
77 E_CREATE, // Unable to create image file
78 E_ABORTED // Read/write error
79 };
80
81
82 void usage( void )
83 {
84 puts(
85
86 "ISOBAR, Version "PVERS" ("PDATE"). Freeware.\n"
87 "\n"
88 "Extract the boot image (or code) from .ISO image of a bootable CD-ROM.\n"
89 "\n"
90 "isobar [-o file] iso-file\n"
91 "\n"
92 "-o file Write the boot image (or code) to the specified filename\n"
93 " (without this, just boot information is displayed).\n"
94 "iso-file An image of a bootable CD-ROM.\n"
95
96 );
97
98 exit( E_OK );
99 }
100
101
102 int main( int argc, char* argv[] )
103 {
104 int i;
105 int fdout = 0;
106 char *outfile = NULL, *isofile = NULL;
107 DWORD bootfound;
108 int type;
109 DWORD n;
110 UINT len, w;
111
112
113 if (argc > 1)
114 {
115 if (argv[1][0] == '?' || argv[1][1] == '?' || !strcmp( argv[1], "--help" ))
116 usage();
117
118 for (i = 1; i < argc; ++i)
119 {
120 if (*argv[i] == '-')
121 {
122 switch (argv[i][1] | 0x20)
123 {
124 case 'o':
125 if (argv[i][2] == '\0' && argv[i+1] == NULL)
126 {
127 fputs( "ERROR: -o requires filename.\n", stderr );
128 return E_OPT;
129 }
130 outfile = (argv[i][2] == '\0') ? argv[++i] : argv[i] + 2;
131 break;
132
133 case 'h':
134 usage ();
135 break;
136
137 default:
138 fprintf( stderr, "ERROR: unknown option: %s.\n", argv[i] );
139 return E_OPT;
140 }
141 }
142 else
143 {
144 isofile = argv[i];
145 }
146 }
147 } else usage();
148
149
150 fdin = open( isofile, O_RDONLY );
151
152 if (fdin == -1)
153 {
154 fprintf( stderr, "ERROR: Cannot open %s.\n", isofile );
155 return E_NOCD;
156 }
157
158 buf = malloc( MAX << 11 ); // transfer up to MAX Sectors (0x800) at a time
159 if (buf == NULL)
160 {
161 fputs( "ERROR: Not enough memory.\n", stderr );
162 return E_MEM;
163 }
164
165 if (!CDRead( 1, 0x11 )) // read the boot record
166 {
167 fputs( "Read error!\n", stderr );
168 return E_ABORTED;
169 }
170
171 if (strcmp( buf+1, "CD001\01EL TORITO SPECIFICATION" ))
172 {
173 fprintf( stderr, "ERROR: %s is not EL TORITO.\n", isofile );
174 return E_NOCD;
175 }
176 bootfound = *(DWORD *)(buf+0x47);
177 printf( "Catalog Sector:\t%lx\n", (long unsigned int)bootfound );
178
179 if (!CDRead( 1, bootfound )) // read the boot catalog
180 {
181 fputs( "Read error!\n", stderr );
182 return E_ABORTED;
183 }
184
185 // Just check the key bytes, don't worry about the checksum.
186 if (buf[0x1e] != (char)0x55 || buf[0x1f] != (char)0xAA)
187 {
188 fprintf( stderr, "ERROR: %s has an invalid boot catalog.\n", isofile );
189 return E_NOCD;
190 }
191 type = (BYTE)buf[1];
192 printf( "Platform:\t%s (%02x)\n", (type < 3) ? platform[type] : "unknown",
193 type );
194 printf( "ID String:\t%.24s\n", (buf[4]) ? buf+4 : "not recorded" );
195 printf( "Bootable:\t%s (%02x)\n", (buf[0x20] == (char)0x88) ? "yes" : "no",
196 (BYTE)buf[0x20] );
197 type = buf[0x21] & 15;
198 printf( "Boot Type:\t%s (%02x)\n", (type < 5) ? boot_type[type] : "unknown",
199 (BYTE)buf[0x21] );
200 i = *(WORD *)(buf+0x22);
201 printf( "Load Segment:\t%04x\n", (i == 0) ? 0x7c0 : i );
202 printf( "System Type:\t%02x\n", (BYTE)buf[0x24] );
203 imgsize = *(WORD *)(buf+0x26);
204 printf( "Sector Count:\t%02x (%d)\n", (UINT)imgsize, (UINT)imgsize );
205 offset = *(DWORD *)(buf+0x28);
206 printf( "Image Sector:\t%lx\n", (long unsigned int)offset );
207
208 switch (type)
209 {
210 case 0: // no emulation
211 break;
212
213 case 1: // 1.2meg floppy
214 imgsize=1200*2;
215 break;
216
217 case 2: // 1.44meg floppy
218 imgsize=1440*2;
219 break;
220
221 case 3: // 2.88meg floppy
222 imgsize=2880*2;
223 break;
224
225 case 4: // hard disk
226 CDRead( 1, offset ); // read the MBR
227 imgsize = *(DWORD *)(buf+0x1c6) + *(DWORD *)(buf+0x1ca); // offset + size of the first partition
228 break;
229
230 default:
231 fprintf( stderr, "ERROR: EL TORITO boot media type not recognized\n", isofile );
232 return E_NOCD;
233 }
234
235 imgsize *= 0x200; // Virtual Sector size = 0x200
236 printf( "Image Size:\t%ld bytes\n", (long int)imgsize );
237
238 if (outfile)
239 {
240 fdout = open( outfile, OFLAG, OMODE );
241 if (fdout < 0)
242 {
243 fprintf( stderr, "ERROR: Cannot create %s.\n", outfile );
244 return E_CREATE;
245 }
246
247 do
248 {
249 n = imgsize >> 11; // Sector size = 0x800
250 if (n > MAX)
251 n = MAX;
252 else if (n == 0)
253 n = 1;
254 if (!CDRead( (UINT)n, offset ))
255 {
256 fputs( "Read error!", stderr );
257 return E_ABORTED;
258 }
259 len = (UINT)n << 11;
260 if (len > imgsize)
261 len = (UINT)imgsize;
262 w = write( fdout, buf, len );
263 if (w != len)
264 {
265 fputs( "Write error!", stderr );
266 return E_ABORTED;
267 }
268 offset += n;
269 imgsize -= len;
270 } while (imgsize);
271 close( fdout );
272 printf( "\nThe output image has been saved in: %s\n", outfile );
273 }
274
275 close( fdin );
276 return 0;
277 }

  ViewVC Help
Powered by ViewVC 1.1.26