wok view syslinux/stuff/iso2exe/iso9660.c @ rev 17473

syslinux/iso2exe: add 64bits support
author Pascal Bellard <pascal.bellard@slitaz.org>
date Sat Dec 27 17:56:57 2014 +0100 (2014-12-27)
parents 7d300004a3b8
children 054f70cb9bec
line source
1 #include <sys/types.h>
2 #include <fcntl.h>
3 #include <stdio.h>
4 #include "iso9660.h"
5 #define __ROCKRIDGE
6 #asm
7 use16 86
8 #endasm
10 char *isofilename;
11 unsigned long isofileofs, isofilesize;
12 unsigned short isofilemod;
13 int isofd;
15 #define SECTORSZ 2048
16 #define SECTORBITS 11
17 static char buffer[SECTORSZ];
19 static int readsector(unsigned long offset)
20 {
21 return (lseek(isofd, offset, SEEK_SET) != -1
22 && read(isofd, buffer, SECTORSZ) == SECTORSZ);
23 }
25 int isoread(char *data, unsigned size)
26 {
27 int get, n;
29 if (size > isofilesize)
30 size = isofilesize;
31 if (lseek(isofd, isofileofs, SEEK_SET) == -1)
32 return -1;
33 for (get = size; get; get -= n, data += n) {
34 n = read(isofd,data,get);
35 if (n < 0)
36 return n;
37 if (n == 0)
38 break;
39 isofileofs += n;
40 isofilesize -= n;
41 }
42 return size - get;
43 }
45 static unsigned long isodirofs, isodirsize;
46 int isoreset(char *name)
47 {
48 if (name)
49 isofd = open(name, O_RDONLY);
50 if (!readsector(16UL * 2048) || strncmp(buffer+1,"CD001",5))
51 return -1;
52 isodirofs = * (unsigned long *) (buffer + 0x9E);
53 isodirofs <<= SECTORBITS;
54 isodirsize = * (unsigned long *) (buffer + 0xA6);
55 return 0;
56 }
58 int isoreaddir(int restart)
59 {
60 static unsigned long pos, dirofs, dirsize;
61 static char dots[] = "..";
62 int size, n;
63 #ifdef __ROCKRIDGE
64 char *endname;
65 #endif
67 if (restart) {
68 dirofs = isodirofs;
69 dirsize = isodirsize;
70 pos = SECTORSZ;
71 }
72 if (pos >= SECTORSZ) {
73 if (dirsize < SECTORSZ) return -1;
74 readsector(dirofs);
75 dirofs += SECTORSZ;
76 dirsize -= SECTORSZ;
77 pos = 0;
78 }
79 size = * (short *) (buffer + pos);
80 if (size == 0)
81 return -1;
82 isofileofs = (* (unsigned long *) (buffer + pos + 2)) << SECTORBITS;
83 isofilesize = * (unsigned long *) (buffer + pos + 10);
84 isofilemod = (buffer[pos + 25] & 2) ? 0040755 : 0100755;
85 #ifdef __ROCKRIDGE
86 endname = NULL;
87 n = (buffer[pos + 32] + pos + 34) & -2;
88 do {
89 int len = buffer[n + 2];
90 switch (* (short *) (buffer + n)) {
91 case 0x4D4E: // NM
92 isofilename = buffer + n + 5;
93 endname = buffer + n + len;
94 break;
95 case 0x5850: // PX
96 isofilemod = * (short *) (buffer + n + 4);
97 break;
98 }
99 n += len;
100 }
101 while (n + 2 < pos + size);
102 if (endname)
103 *endname = 0;
104 else
105 #endif
106 {
107 isofilename = buffer + pos + 33;
108 switch (* (short *) (isofilename - 1)) {
109 case 0x0101:
110 isofilename = dots;
111 break;
112 case 0x0001:
113 isofilename = dots + 1;
114 break;
115 default:
116 n = isofilename[-1];
117 if (* (short *) (isofilename + n - 2) == 0x313B)
118 n -= 2; // remove ;1
119 if (isofilename[n - 1] == '.') n--;
120 isofilename[n] = 0;
121 }
122 }
123 pos += size;
124 return 0;
125 }
127 static int cpuhaslm(void)
128 {
129 #asm
130 pushf // save flags
131 // bits 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
132 // flags 0 NT IOPL OF DF IF TF SF ZF 0 AF 0 PF 1 CF
133 mov ax, #0x1000
134 push ax
135 popf // < 286 : flags[12..15] are forced 1
136 pushf // = 286 : flags[12..15] are forced 0
137 pop bx // > 286 : only flags[15] is forced 0
138 popf // restore flags (IOPL)
139 add bh, ah // test F0 and 00 cases
140 cmp bh, ah
141 cbw
142 jbe not386 // C=8086/80186, Z=80286
143 use16 386
144 pushfd
145 pushfd
146 pop ebx
147 mov ecx, ebx
148 btc ebx, #21 // toggle CPUID feature bit
149 push ebx
150 popfd
151 pushfd
152 pop ebx
153 popfd
154 xor ebx, ecx
155 bt ebx, #21 // CPUID feature bit ?
156 jnc nocpuid
157 mov eax, #0x80000001 // Extended Processor Info and Feature Bits
158 .byte 0x0F, 0xA2 // cpuid
159 xor ax, ax
160 bt edx, #29 // LM feature bit ?
161 adc ax, ax
162 use16 86
163 nocpuid:
164 not386:
165 #endasm
166 }
168 #define IS_DIR(x)( ((x) & ~0777) == 040000)
169 int isoopen(char *filename)
170 {
171 int restart;
172 char *name, *s, c;
173 int _64bits = cpuhaslm();
175 retry32:
176 name = filename;
177 while (*name == '/') {
178 name++;
179 isoreset(NULL);
180 }
181 s = name;
182 while (1) {
183 while (*s && *s != '/') s++;
184 c = *s;
185 *s = 0;
186 for (restart = 1; isoreaddir(restart) == 0; restart = 0) {
187 char *n = name, *i = isofilename;
188 if (_64bits) {
189 int len = strlen(name);
190 if (strncmp(name, isofilename), len) continue;
191 n = "64";
192 i += len;
193 }
194 if (strcmp(n, i)) continue;
195 if (IS_DIR(isofilemod)) {
196 isodirofs = isofileofs;
197 isodirsize = isofilesize;
198 if (c) {
199 *s++ = c;
200 name = s;
201 goto next;
202 }
203 }
204 return 0;
205 }
206 if (_64bits) {
207 _64bits = 0;
208 *s = c;
209 goto retry32;
210 }
211 return -1;
212 next: ;
213 }
214 }