wok view syslinux/stuff/iso2exe/win32.c @ rev 14264

syslinux/iso2exe: fix initrd offset
author Pascal Bellard <pascal.bellard@slitaz.org>
date Mon Apr 01 09:45:40 2013 +0200 (2013-04-01)
parents 692d9593f959
children ff85ea851c53
line source
1 #include <windows.h>
2 #include <winnt.h>
3 #include <sys/types.h>
4 #include <sys/stat.h>
5 #include <fcntl.h>
7 #define BOOTSTRAP_SECTOR_COUNT_OFFSET 28
9 static int fullread(int fd, char *p, int n)
10 {
11 int i, j;
12 for (i = 0; n > 0; i += j, n -= j) {
13 j = read(fd, p + i, n);
14 if (j <= 0) break;
15 }
16 return i;
17 #define read fullread
18 }
20 static int fullwrite(int fd, char *p, int n)
21 {
22 int i, j;
23 for (i = 0; n > 0; i += j, n -= j) {
24 j = write(fd, p + i, n);
25 if (j <= 0) break;
26 }
27 return i;
28 #define write fullwrite
29 }
31 static void exec16bits(char *isoFileName)
32 {
33 int fdiso, fdtmp, i;
34 long buffer[512/4];
35 char tmpFileName[MAX_PATH], *p;
37 strcpy(tmpFileName, isoFileName);
38 p = strrchr(tmpFileName, '\\');
39 if (!p++) p = tmpFileName;
40 strcpy(p, "tazboot.exe");
41 fdiso = open(isoFileName, O_RDONLY|O_BINARY);
42 fdtmp = open(tmpFileName, O_WRONLY|O_BINARY|O_CREAT,0555);
43 for (i = 0; i < 0x8000; i += sizeof(buffer)) {
44 read(fdiso, (char *) buffer, sizeof(buffer));
45 if (i == 0) buffer[15] = 0; // kill PE header
46 write(fdtmp, (char *) buffer, sizeof(buffer));
47 }
48 close(fdiso);
49 close(fdtmp);
50 execl(tmpFileName, isoFileName);
51 }
53 static int iswinnt(void)
54 {
55 OSVERSIONINFOA Version;
56 Version.dwOSVersionInfoSize = sizeof(Version);
57 return (GetVersionEx(&Version) &&
58 Version.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS); // not Win9x
59 }
61 static int ishybrid(char *isoFileName)
62 {
63 int fdiso;
64 char buffer[2048];
65 unsigned long magic = 0;
67 fdiso = open(isoFileName, O_RDONLY|O_BINARY);
68 if (lseek(fdiso, 17 * 2048L, SEEK_SET) != -1 &&
69 read(fdiso, buffer, 2048) == 2048 &&
70 strncmp(buffer+23,"EL TORITO SPECIFICATION",23) == 0) {
71 unsigned long lba = * (unsigned long *) (buffer + 71);
73 if (lseek(fdiso, lba * 2048L, SEEK_SET) != -1 &&
74 read(fdiso, buffer, 2048) == 2048 &&
75 * (unsigned long *) (buffer + 0) == 1 &&
76 * (unsigned long *) (buffer + 30) == 0x88AA55) {
77 lba = * (unsigned long *) (buffer + 40);
78 if (lseek(fdiso, lba * 2048L, SEEK_SET) != -1 &&
79 read(fdiso, buffer, 2048) == 2048)
80 magic = * (unsigned long *) (buffer + 64);
81 }
82 }
83 close(fdiso);
84 return (magic == 1886961915);
85 }
87 #define MODE_READ 0
88 #define MODE_WRITE 1
89 static int rdwrsector(int mode, int drive, unsigned long startingsector,
90 unsigned long count, char *buffer)
91 {
92 HANDLE hDevice;
93 DWORD result;
94 char devname[sizeof("\\\\.\\PhysicalDrive0")];
96 if (drive >= 128) {
97 strcpy(devname, "\\\\.\\PhysicalDrive0");
98 devname[17] += drive - 128;
99 }
100 else {
101 strcpy(devname, "\\\\.\\A:");
102 devname[4] += drive;
103 }
104 hDevice = CreateFile (devname, GENERIC_READ,
105 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
106 if (hDevice == INVALID_HANDLE_VALUE)
107 return -1;
108 SetFilePointer(hDevice, (startingsector*512), NULL, FILE_BEGIN);
109 if (mode == MODE_READ) {
110 if (!ReadFile(hDevice, buffer, 512*count, &result, NULL))
111 result = -1;
112 }
113 else {
114 if (!WriteFile(hDevice, buffer, 512*count, &result, NULL))
115 result = -1;
116 }
117 CloseHandle(hDevice);
118 return result;
119 }
121 static void rawrite(unsigned long drive, char *isoFileName)
122 {
123 int fdiso, s, dev, isohybrid = -1;
124 char buffer[2048];
126 if (drive == 0) return;
127 for (dev = 128; (drive & 1) == 0; dev++)
128 drive >>= 1;
129 fdiso = open(isoFileName, O_RDONLY|O_BINARY);
130 for (s = 0;;) {
131 int s, n = read(fdiso, buffer, sizeof(buffer));
132 if (n <= 0) break;
133 n = (n+511)/512;
134 if (s == 0) isohybrid = buffer[69];
135 rdwrsector(MODE_WRITE, dev, s, n, buffer);
136 if (s == isohybrid)
137 rdwrsector(MODE_WRITE, dev, 0, 1, buffer);
138 s += n;
139 }
140 close(fdiso);
141 }
143 static unsigned long drives(void)
144 {
145 int i, mask, result;
146 char buffer[512];
147 for (i = result = 0, mask = 1; i < 8; i++, mask <<= 1) {
148 if (rdwrsector(MODE_READ, i+128, 0, 1, buffer) != -1)
149 result |= mask;
150 }
151 return result;
152 }
154 static void writefloppy(char *isoFileName)
155 {
156 char buffer[512];
157 int i, n, fd;
159 buffer[BOOTSTRAP_SECTOR_COUNT_OFFSET] = 0;
160 fd = open(isoFileName, O_RDONLY|O_BINARY);
161 if (fd != -1) {
162 read(fd, buffer, sizeof(buffer));
163 n = buffer[BOOTSTRAP_SECTOR_COUNT_OFFSET];
164 if (n != 0 &&
165 lseek(fd, * (unsigned short *) (buffer + 66) - (512 * n),
166 SEEK_SET) != -1) {
167 for (i = 0; i < n; i++) {
168 read(fd, buffer, 512);
169 if (i == 1) strncpy(buffer, isoFileName, 512);
170 rdwrsector(MODE_WRITE, 0, i, 1, buffer);
171 }
172 }
173 close(fd);
174 }
175 }
177 //TODO #define VCPI_LINUX_LOADER The DOS/EXE loader can boot in VM86 using VCPI API
178 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
179 LPSTR lpCmdLine, int nCmdShow)
180 {
181 char isoFileName[MAX_PATH];
182 char header[32];
183 int fd;
184 int usbkeyicon = MB_ICONASTERISK;
185 char *usbkeymsg = "You can either:\n\n"
186 "- create a SliTaz USB boot key or a boot memory card.\n"
187 " (note that this will be read only like a CDROM.\n"
188 " The Slitaz utility 'tazusb' can be used later to create\n"
189 " a true read/write USB key).\n\n"
190 "- create a SliTaz bootstrap floppy for the ISO image\n"
191 " on the hard disk.\n"
192 "\nDo you want to create a boot key now ?";
194 GetModuleFileName(hInstance, isoFileName, MAX_PATH);
195 if (!iswinnt()) {
196 #ifdef VCPI_LINUX_LOADER
197 exec16bits(isoFileName);
198 #else
199 MessageBox(NULL,"No support for Win9x yet.\n"
200 "Retry in DOS mode without emm386.\n",
201 "Sorry", MB_OK|MB_ICONERROR);
202 exit(1);
203 #endif
204 }
205 if (!ishybrid(isoFileName)) {
206 if (MessageBox(NULL,"Not an isolinux hybrid ISO.\n"
207 "This ISO image will not boot\n"
208 "from the media that you create !",
209 "Will not boot !",
210 MB_OKCANCEL|MB_ICONWARNING) == IDCANCEL)
211 exit(0);
212 }
213 header[BOOTSTRAP_SECTOR_COUNT_OFFSET] = 0;
214 fd = open(isoFileName, O_RDONLY|O_BINARY);
215 if (fd != -1) {
216 read(fd, header, sizeof(header));
217 close(fd);
218 }
219 if (header[BOOTSTRAP_SECTOR_COUNT_OFFSET] == 0) { // No floppy bootstrap available
220 usbkeyicon = MB_ICONQUESTION;
221 usbkeymsg = "Do you want to create a boot key ?";
222 }
223 if (MessageBox(NULL,usbkeymsg, "Create a boot stick ?",
224 MB_YESNO|usbkeyicon) == IDYES) {
225 unsigned long base, new;
226 int retry;
228 if (MessageBox(NULL,"Step 1: unplug the USB stick.",
229 "Drive detection 1/2",
230 MB_OKCANCEL|MB_ICONEXCLAMATION) == IDCANCEL)
231 exit(0);
232 base = drives();
233 if (MessageBox(NULL,"Step 2: plug the USB stick in.",
234 "Drive detection 2/2",
235 MB_OKCANCEL|MB_ICONEXCLAMATION) == IDCANCEL)
236 exit(0);
237 retry = 0;
238 do {
239 Sleep(1000); // ms
240 new = drives();
241 } while (new == base && retry++ < 10);
242 if (new == base) {
243 MessageBox(NULL,"No USB stick found.","Sorry",
244 MB_OK|MB_ICONERROR);
245 exit(1);
246 }
247 rawrite(base ^ new, isoFileName);
248 }
249 if (header[BOOTSTRAP_SECTOR_COUNT_OFFSET] != 0 &&
250 MessageBox(NULL,"Do you want to create a bootstrap floppy ?",
251 "Create a bootstrap floppy ?",
252 MB_YESNO|MB_ICONQUESTION) == IDYES &&
253 MessageBox(NULL,"Insert a floppy disk in drive now",
254 "Insert floppy",
255 MB_OKCANCEL|MB_ICONEXCLAMATION) != IDCANCEL) {
257 // Create a 9k bootstrap with vfat, ext2 & ntfs drivers
258 // to boot the ISO image on hard disk
259 writefloppy(isoFileName);
260 }
261 }