wok-next annotate syslinux/stuff/extra/md5sum.c @ rev 18471
syslinux: receipt formatting (Pascal already removed lines, so it is :)
help.en: 4000 -> 5000 packages
help.en: 4000 -> 5000 packages
author | Aleksej Bobylev <al.bobylev@gmail.com> |
---|---|
date | Sat Oct 03 16:36:26 2015 +0300 (2015-10-03) |
parents | 0b3e30f655f9 |
children | cc264cb074e2 |
rev | line source |
---|---|
pascal@12210 | 1 /* |
pascal@12215 | 2 * Based on busybox code. |
pascal@12210 | 3 * |
pascal@12215 | 4 * Compute MD5 checksum of strings according to the |
pascal@12215 | 5 * definition of MD5 in RFC 1321 from April 1992. |
pascal@12210 | 6 * |
pascal@12215 | 7 * Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. |
pascal@12215 | 8 * |
pascal@12215 | 9 * Copyright (C) 1995-1999 Free Software Foundation, Inc. |
pascal@12215 | 10 * Copyright (C) 2001 Manuel Novoa III |
pascal@12215 | 11 * Copyright (C) 2003 Glenn L. McGrath |
pascal@12215 | 12 * Copyright (C) 2003 Erik Andersen |
pascal@12210 | 13 * Copyright (C) 2010 Denys Vlasenko |
pascal@12215 | 14 * Copyright (C) 2012 Pascal Bellard |
pascal@12210 | 15 * |
pascal@12215 | 16 * Licensed under GPLv2 or later |
pascal@12210 | 17 */ |
pascal@12210 | 18 |
pascal@12210 | 19 #include <stdio.h> |
pascal@12210 | 20 #include <stdlib.h> |
pascal@12210 | 21 #include <string.h> |
pascal@12210 | 22 #include <unistd.h> |
pascal@12210 | 23 #include <fcntl.h> |
pascal@12210 | 24 #include <console.h> |
pascal@12210 | 25 #include <com32.h> |
pascal@12210 | 26 |
pascal@12210 | 27 #define ALIGN1 |
pascal@12215 | 28 |
pascal@12215 | 29 static uint8_t wbuffer[64]; /* always correctly aligned for uint64_t */ |
pascal@12215 | 30 static uint64_t total64; /* must be directly before hash[] */ |
pascal@12215 | 31 static uint32_t hash[8]; /* 4 elements for md5, 5 for sha1, 8 for sha256 */ |
pascal@12210 | 32 |
pascal@12210 | 33 /* Emit a string of hex representation of bytes */ |
pascal@12215 | 34 static char* bin2hex(char *p) |
pascal@12210 | 35 { |
pascal@12215 | 36 static const char bb_hexdigits_upcase[] ALIGN1 = "0123456789abcdef"; |
pascal@12215 | 37 int count = 16; |
pascal@12215 | 38 const char *cp = (const char *) hash; |
pascal@12210 | 39 while (count) { |
pascal@12210 | 40 unsigned char c = *cp++; |
pascal@12210 | 41 /* put lowercase hex digits */ |
pascal@12215 | 42 *p++ = bb_hexdigits_upcase[c >> 4]; |
pascal@12215 | 43 *p++ = bb_hexdigits_upcase[c & 0xf]; |
pascal@12210 | 44 count--; |
pascal@12210 | 45 } |
pascal@12210 | 46 return p; |
pascal@12210 | 47 } |
pascal@12210 | 48 |
pascal@12210 | 49 //#define rotl32(x,n) (((x) << (n)) | ((x) >> (32 - (n)))) |
pascal@12210 | 50 static uint32_t rotl32(uint32_t x, unsigned n) |
pascal@12210 | 51 { |
pascal@12210 | 52 return (x << n) | (x >> (32 - n)); |
pascal@12210 | 53 } |
pascal@12210 | 54 |
pascal@12215 | 55 static void md5_process_block64(void); |
pascal@12210 | 56 |
pascal@12210 | 57 /* Feed data through a temporary buffer. |
pascal@12210 | 58 * The internal buffer remembers previous data until it has 64 |
pascal@12210 | 59 * bytes worth to pass on. |
pascal@12210 | 60 */ |
pascal@12215 | 61 static void common64_hash(const void *buffer, size_t len) |
pascal@12210 | 62 { |
pascal@12215 | 63 unsigned bufpos = total64 & 63; |
pascal@12210 | 64 |
pascal@12215 | 65 total64 += len; |
pascal@12210 | 66 |
pascal@12210 | 67 while (1) { |
pascal@12210 | 68 unsigned remaining = 64 - bufpos; |
pascal@12210 | 69 if (remaining > len) |
pascal@12210 | 70 remaining = len; |
pascal@12210 | 71 /* Copy data into aligned buffer */ |
pascal@12215 | 72 memcpy(wbuffer + bufpos, buffer, remaining); |
pascal@12210 | 73 len -= remaining; |
pascal@12210 | 74 buffer = (const char *)buffer + remaining; |
pascal@12210 | 75 bufpos += remaining; |
pascal@12210 | 76 /* clever way to do "if (bufpos != 64) break; ... ; bufpos = 0;" */ |
pascal@12210 | 77 bufpos -= 64; |
pascal@12210 | 78 if (bufpos != 0) |
pascal@12210 | 79 break; |
pascal@12210 | 80 /* Buffer is filled up, process it */ |
pascal@12215 | 81 md5_process_block64(); |
pascal@12210 | 82 /*bufpos = 0; - already is */ |
pascal@12210 | 83 } |
pascal@12210 | 84 } |
pascal@12210 | 85 |
pascal@12210 | 86 /* Process the remaining bytes in the buffer */ |
pascal@12215 | 87 static void common64_end(void) |
pascal@12210 | 88 { |
pascal@12215 | 89 unsigned bufpos = total64 & 63; |
pascal@12210 | 90 /* Pad the buffer to the next 64-byte boundary with 0x80,0,0,0... */ |
pascal@12215 | 91 wbuffer[bufpos++] = 0x80; |
pascal@12210 | 92 |
pascal@12210 | 93 /* This loop iterates either once or twice, no more, no less */ |
pascal@12210 | 94 while (1) { |
pascal@12210 | 95 unsigned remaining = 64 - bufpos; |
pascal@12215 | 96 memset(wbuffer + bufpos, 0, remaining); |
pascal@12210 | 97 /* Do we have enough space for the length count? */ |
pascal@12210 | 98 if (remaining >= 8) { |
pascal@12210 | 99 /* Store the 64-bit counter of bits in the buffer */ |
pascal@12215 | 100 uint64_t t = total64 << 3; |
pascal@12210 | 101 /* wbuffer is suitably aligned for this */ |
pascal@12215 | 102 *(uint64_t *) (&wbuffer[64 - 8]) = t; |
pascal@12210 | 103 } |
pascal@12215 | 104 md5_process_block64(); |
pascal@12210 | 105 if (remaining >= 8) |
pascal@12210 | 106 break; |
pascal@12210 | 107 bufpos = 0; |
pascal@12210 | 108 } |
pascal@12210 | 109 } |
pascal@12210 | 110 |
pascal@12210 | 111 /* These are the four functions used in the four steps of the MD5 algorithm |
pascal@12210 | 112 * and defined in the RFC 1321. The first function is a little bit optimized |
pascal@12210 | 113 * (as found in Colin Plumbs public domain implementation). |
pascal@12210 | 114 * #define FF(b, c, d) ((b & c) | (~b & d)) |
pascal@12210 | 115 */ |
pascal@12210 | 116 #undef FF |
pascal@12210 | 117 #undef FG |
pascal@12210 | 118 #undef FH |
pascal@12210 | 119 #undef FI |
pascal@12210 | 120 #define FF(b, c, d) (d ^ (b & (c ^ d))) |
pascal@12210 | 121 #define FG(b, c, d) FF(d, b, c) |
pascal@12210 | 122 #define FH(b, c, d) (b ^ c ^ d) |
pascal@12210 | 123 #define FI(b, c, d) (c ^ (b | ~d)) |
pascal@12210 | 124 |
pascal@12210 | 125 /* Hash a single block, 64 bytes long and 4-byte aligned */ |
pascal@12215 | 126 static void md5_process_block64(void) |
pascal@12210 | 127 { |
pascal@12210 | 128 /* Before we start, one word to the strange constants. |
pascal@12210 | 129 They are defined in RFC 1321 as |
pascal@12210 | 130 T[i] = (int)(4294967296.0 * fabs(sin(i))), i=1..64 |
pascal@12210 | 131 */ |
pascal@12210 | 132 static const uint32_t C_array[] = { |
pascal@12210 | 133 /* round 1 */ |
pascal@12210 | 134 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, |
pascal@12210 | 135 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, |
pascal@12210 | 136 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, |
pascal@12210 | 137 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, |
pascal@12210 | 138 /* round 2 */ |
pascal@12210 | 139 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, |
pascal@12210 | 140 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, |
pascal@12210 | 141 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, |
pascal@12210 | 142 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, |
pascal@12210 | 143 /* round 3 */ |
pascal@12210 | 144 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, |
pascal@12210 | 145 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, |
pascal@12210 | 146 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05, |
pascal@12210 | 147 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, |
pascal@12210 | 148 /* round 4 */ |
pascal@12210 | 149 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, |
pascal@12210 | 150 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, |
pascal@12210 | 151 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, |
pascal@12210 | 152 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 |
pascal@12210 | 153 }; |
pascal@12210 | 154 static const char P_array[] ALIGN1 = { |
pascal@12210 | 155 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 1 */ |
pascal@12210 | 156 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, /* 2 */ |
pascal@12210 | 157 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, /* 3 */ |
pascal@12210 | 158 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 /* 4 */ |
pascal@12210 | 159 }; |
pascal@12215 | 160 uint32_t *words = (void*) wbuffer; |
pascal@12215 | 161 uint32_t A = hash[0]; |
pascal@12215 | 162 uint32_t B = hash[1]; |
pascal@12215 | 163 uint32_t C = hash[2]; |
pascal@12215 | 164 uint32_t D = hash[3]; |
pascal@12210 | 165 |
pascal@12210 | 166 static const char S_array[] ALIGN1 = { |
pascal@12210 | 167 7, 12, 17, 22, |
pascal@12210 | 168 5, 9, 14, 20, |
pascal@12210 | 169 4, 11, 16, 23, |
pascal@12210 | 170 6, 10, 15, 21 |
pascal@12210 | 171 }; |
pascal@12210 | 172 const uint32_t *pc; |
pascal@12210 | 173 const char *pp; |
pascal@12210 | 174 const char *ps; |
pascal@12210 | 175 int i; |
pascal@12210 | 176 uint32_t temp; |
pascal@12210 | 177 |
pascal@12210 | 178 |
pascal@12210 | 179 pc = C_array; |
pascal@12210 | 180 pp = P_array; |
pascal@12210 | 181 ps = S_array - 4; |
pascal@12210 | 182 |
pascal@12210 | 183 for (i = 0; i < 64; i++) { |
pascal@12210 | 184 if ((i & 0x0f) == 0) |
pascal@12210 | 185 ps += 4; |
pascal@12210 | 186 temp = A; |
pascal@12210 | 187 switch (i >> 4) { |
pascal@12210 | 188 case 0: |
pascal@12210 | 189 temp += FF(B, C, D); |
pascal@12210 | 190 break; |
pascal@12210 | 191 case 1: |
pascal@12210 | 192 temp += FG(B, C, D); |
pascal@12210 | 193 break; |
pascal@12210 | 194 case 2: |
pascal@12210 | 195 temp += FH(B, C, D); |
pascal@12210 | 196 break; |
pascal@12210 | 197 case 3: |
pascal@12210 | 198 temp += FI(B, C, D); |
pascal@12210 | 199 } |
pascal@12210 | 200 temp += words[(int) (*pp++)] + *pc++; |
pascal@12210 | 201 temp = rotl32(temp, ps[i & 3]); |
pascal@12210 | 202 temp += B; |
pascal@12210 | 203 A = D; |
pascal@12210 | 204 D = C; |
pascal@12210 | 205 C = B; |
pascal@12210 | 206 B = temp; |
pascal@12210 | 207 } |
pascal@12210 | 208 /* Add checksum to the starting values */ |
pascal@12215 | 209 hash[0] += A; |
pascal@12215 | 210 hash[1] += B; |
pascal@12215 | 211 hash[2] += C; |
pascal@12215 | 212 hash[3] += D; |
pascal@12210 | 213 |
pascal@12210 | 214 } |
pascal@12210 | 215 #undef FF |
pascal@12210 | 216 #undef FG |
pascal@12210 | 217 #undef FH |
pascal@12210 | 218 #undef FI |
pascal@12210 | 219 |
pascal@12210 | 220 /* Initialize structure containing state of computation. |
pascal@12210 | 221 * (RFC 1321, 3.3: Step 3) |
pascal@12210 | 222 */ |
pascal@12215 | 223 static void md5_begin(void) |
pascal@12210 | 224 { |
pascal@12215 | 225 hash[0] = 0x67452301; |
pascal@12215 | 226 hash[1] = 0xefcdab89; |
pascal@12215 | 227 hash[2] = 0x98badcfe; |
pascal@12215 | 228 hash[3] = 0x10325476; |
pascal@12215 | 229 total64 = 0; |
pascal@12210 | 230 } |
pascal@12210 | 231 |
pascal@12210 | 232 /* Used also for sha1 and sha256 */ |
pascal@12215 | 233 #define md5_hash common64_hash |
pascal@12210 | 234 |
pascal@12210 | 235 /* Process the remaining bytes in the buffer and put result from CTX |
pascal@12210 | 236 * in first 16 bytes following RESBUF. The result is always in little |
pascal@12210 | 237 * endian byte order, so that a byte-wise output yields to the wanted |
pascal@12210 | 238 * ASCII representation of the message digest. |
pascal@12210 | 239 */ |
pascal@12215 | 240 #define md5_end common64_end |
pascal@12210 | 241 |
pascal@12210 | 242 /* |
pascal@12210 | 243 * Copyright (C) 2003 Glenn L. McGrath |
pascal@12210 | 244 * Copyright (C) 2003-2004 Erik Andersen |
pascal@12210 | 245 * |
pascal@12210 | 246 * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
pascal@12210 | 247 */ |
pascal@12210 | 248 |
pascal@12215 | 249 static char *unrockridge(const char *name) |
pascal@12212 | 250 { |
pascal@12212 | 251 static char buffer[256]; |
pascal@12215 | 252 int i = 0, j = 8; |
pascal@12215 | 253 while (*name && i < 255) { |
pascal@12215 | 254 char c = *name++; |
pascal@12215 | 255 //if (c == '\\') c = '/'; |
pascal@12215 | 256 if (c == '.') { |
pascal@12215 | 257 for (j = i; --j >= 0 && buffer[j] != '/';) |
pascal@12215 | 258 if (buffer[j] == '.') buffer[j] = '_'; |
pascal@12215 | 259 if (i - j > 9) i = j + 9; |
pascal@12215 | 260 j = i + 4; |
pascal@12212 | 261 } |
pascal@12215 | 262 else if (c == '/') j = i + 9; |
pascal@12212 | 263 else if (i >= j) continue; |
pascal@12215 | 264 else if (c >= 'a' && c <= 'z') c += 'A' - 'a'; |
pascal@12215 | 265 else if ((c < 'A' || c > 'Z') && (c < '0' || c > '9')) c = '_'; |
pascal@12215 | 266 buffer[i++] = c; |
pascal@12212 | 267 } |
pascal@12215 | 268 buffer[i] = 0; |
pascal@12212 | 269 return buffer; |
pascal@12212 | 270 } |
pascal@12212 | 271 |
pascal@12210 | 272 static uint8_t *hash_file(const char *filename) |
pascal@12210 | 273 { |
pascal@12210 | 274 int src_fd, count; |
pascal@12215 | 275 uint8_t in_buf[4096]; |
pascal@12215 | 276 static uint8_t hash_value[16*2+1]; |
pascal@12210 | 277 |
pascal@12210 | 278 src_fd = open(filename, O_RDONLY); |
pascal@12210 | 279 if (src_fd < 0) { |
pascal@12215 | 280 src_fd = open(unrockridge(filename), O_RDONLY); |
pascal@12212 | 281 } |
pascal@12212 | 282 if (src_fd < 0) { |
pascal@12210 | 283 return NULL; |
pascal@12210 | 284 } |
pascal@12210 | 285 |
pascal@12215 | 286 md5_begin(); |
pascal@12210 | 287 while ((count = read(src_fd, in_buf, 4096)) > 0) { |
pascal@12215 | 288 md5_hash(in_buf, count); |
pascal@12210 | 289 } |
pascal@12210 | 290 |
pascal@12210 | 291 close(src_fd); |
pascal@12215 | 292 |
pascal@12215 | 293 if (count) |
pascal@12215 | 294 return NULL; |
pascal@12215 | 295 |
pascal@12215 | 296 md5_end(); |
pascal@12215 | 297 bin2hex((char *)hash_value); |
pascal@12210 | 298 |
pascal@12210 | 299 return hash_value; |
pascal@12210 | 300 } |
pascal@12210 | 301 |
pascal@13295 | 302 static int main_say(int argc, char **argv) |
pascal@13295 | 303 { |
pascal@13295 | 304 int i; |
pascal@13295 | 305 for (i = 1; i < argc; i++) { |
pascal@13295 | 306 printf("%s ",argv[i]); |
pascal@13295 | 307 } |
pascal@13295 | 308 sleep(5); |
pascal@13551 | 309 return 0; |
pascal@13295 | 310 } |
pascal@13295 | 311 |
pascal@12273 | 312 static int main_md5sum(int argc, char **argv) |
pascal@12210 | 313 { |
pascal@12215 | 314 int files = 0, tested = 0, good = 0; |
pascal@12215 | 315 static char clear_eol[] = " "; |
pascal@12210 | 316 |
pascal@12210 | 317 (void) argc; |
pascal@12210 | 318 /* -c implied */ |
pascal@12287 | 319 argv++; |
pascal@12210 | 320 do { |
pascal@12210 | 321 FILE *fp; |
pascal@13361 | 322 char eol, *line, buffer[4096]; |
pascal@12210 | 323 fp = fopen(*argv,"r"); |
pascal@12212 | 324 if (fp == NULL) |
pascal@12215 | 325 fp = fopen(unrockridge(*argv),"r"); |
pascal@12210 | 326 |
pascal@13361 | 327 while ((line = fgets(buffer,sizeof(buffer),fp)) != NULL) { |
pascal@12210 | 328 uint8_t *hash_value; |
pascal@12210 | 329 char *filename_ptr, *status; |
pascal@12210 | 330 int len = strlen(line); |
pascal@12210 | 331 |
pascal@12210 | 332 if (line[0] < '0') |
pascal@12210 | 333 continue; |
pascal@12210 | 334 if (line[len-1] == '\n') |
pascal@12210 | 335 line[len-1] = 0; |
pascal@12210 | 336 filename_ptr = strstr(line, " "); |
pascal@12210 | 337 /* handle format for binary checksums */ |
pascal@12210 | 338 if (filename_ptr == NULL) { |
pascal@12210 | 339 filename_ptr = strstr(line, " *"); |
pascal@12210 | 340 } |
pascal@12210 | 341 if (filename_ptr == NULL) { |
pascal@12210 | 342 continue; |
pascal@12210 | 343 } |
pascal@12210 | 344 *filename_ptr = '\0'; |
pascal@12210 | 345 *++filename_ptr = '/'; |
pascal@12212 | 346 if (filename_ptr[1] == '/') |
pascal@12212 | 347 filename_ptr++; |
pascal@12210 | 348 |
pascal@12215 | 349 files++; |
pascal@12215 | 350 status = "NOT CHECKED"; |
pascal@12215 | 351 eol = '\n'; |
pascal@12211 | 352 hash_value = hash_file(filename_ptr); |
pascal@12211 | 353 if (hash_value) { |
pascal@12215 | 354 tested++; |
pascal@12215 | 355 status = "BROKEN"; |
pascal@12215 | 356 if (!strcmp((char*)hash_value, line)) { |
pascal@12215 | 357 good++; |
pascal@12215 | 358 status = "OK"; |
pascal@12215 | 359 eol = ' '; |
pascal@12210 | 360 } |
pascal@12210 | 361 } |
pascal@12215 | 362 printf("\r%s: %s%s%c", filename_ptr, status, clear_eol, eol); |
pascal@12210 | 363 } |
pascal@12210 | 364 fclose(fp); |
pascal@12210 | 365 } while (*++argv); |
pascal@12215 | 366 printf("\r%d files OK, %d broken, %d not checked.%s\n", |
pascal@12215 | 367 good, tested - good, files - tested, clear_eol); |
pascal@12287 | 368 sleep(5); |
pascal@12273 | 369 return 0; |
pascal@12215 | 370 } |
pascal@12210 | 371 |
pascal@12273 | 372 /* |
pascal@12273 | 373 * ifmem.c |
pascal@12273 | 374 * |
pascal@12273 | 375 * Run one command if the memory is large enought, and another if it isn't. |
pascal@12273 | 376 * |
pascal@12273 | 377 * Usage: |
pascal@12273 | 378 * |
pascal@12273 | 379 * label boot_kernel |
pascal@12273 | 380 * kernel ifmem.c |
pascal@12273 | 381 * append size_in_KB boot_large [size_in_KB boot_medium] boot_small |
pascal@12273 | 382 * |
pascal@12273 | 383 * label boot_large |
pascal@12273 | 384 * kernel vmlinuz_large_memory |
pascal@12273 | 385 * append ... |
pascal@12273 | 386 * |
pascal@12273 | 387 * label boot_small |
pascal@12273 | 388 * kernel vmlinuz_small_memory |
pascal@12273 | 389 * append ... |
pascal@12273 | 390 */ |
pascal@12273 | 391 |
pascal@12273 | 392 #include <inttypes.h> |
pascal@12273 | 393 #include <alloca.h> |
pascal@12273 | 394 #include <syslinux/boot.h> |
pascal@12273 | 395 |
pascal@12273 | 396 struct e820_data { |
pascal@12273 | 397 uint64_t base; |
pascal@12273 | 398 uint64_t len; |
pascal@12273 | 399 uint32_t type; |
pascal@12273 | 400 uint32_t extattr; |
pascal@12273 | 401 } __attribute__((packed)); |
pascal@12273 | 402 |
pascal@12273 | 403 // Get memory size in Kb |
pascal@12273 | 404 static unsigned long memory_size(void) |
pascal@12273 | 405 { |
pascal@12273 | 406 uint64_t bytes = 0; |
pascal@12273 | 407 static com32sys_t ireg, oreg; |
pascal@12273 | 408 static struct e820_data ed; |
pascal@12273 | 409 |
pascal@12273 | 410 ireg.eax.w[0] = 0xe820; |
pascal@12273 | 411 ireg.edx.l = 0x534d4150; |
pascal@12273 | 412 ireg.ecx.l = sizeof(struct e820_data); |
pascal@12273 | 413 ireg.edi.w[0] = OFFS(__com32.cs_bounce); |
pascal@12273 | 414 ireg.es = SEG(__com32.cs_bounce); |
pascal@12273 | 415 |
pascal@12273 | 416 ed.extattr = 1; |
pascal@12273 | 417 |
pascal@12273 | 418 do { |
pascal@12273 | 419 memcpy(__com32.cs_bounce, &ed, sizeof ed); |
pascal@12273 | 420 |
pascal@12273 | 421 __intcall(0x15, &ireg, &oreg); |
pascal@12273 | 422 if (oreg.eflags.l & EFLAGS_CF || |
pascal@12273 | 423 oreg.eax.l != 0x534d4150 || |
pascal@12273 | 424 oreg.ecx.l < 20) |
pascal@12273 | 425 break; |
pascal@12273 | 426 |
pascal@12273 | 427 memcpy(&ed, __com32.cs_bounce, sizeof ed); |
pascal@12273 | 428 |
pascal@12273 | 429 if (ed.type == 1) |
pascal@12273 | 430 bytes += ed.len; |
pascal@12273 | 431 |
pascal@12273 | 432 ireg.ebx.l = oreg.ebx.l; |
pascal@12273 | 433 } while (ireg.ebx.l); |
pascal@12273 | 434 |
pascal@12273 | 435 if (!bytes) { |
pascal@12273 | 436 memset(&ireg, 0, sizeof ireg); |
pascal@12273 | 437 ireg.eax.w[0] = 0x8800; |
pascal@12273 | 438 __intcall(0x15, &ireg, &oreg); |
pascal@12273 | 439 return ireg.eax.w[0]; |
pascal@12273 | 440 } |
pascal@12273 | 441 return bytes >> 10; |
pascal@12273 | 442 } |
pascal@12273 | 443 |
pascal@12349 | 444 static void usage(const char *msg) |
pascal@12349 | 445 { |
pascal@12349 | 446 fprintf(stderr,"\n%s\n.",msg); |
pascal@12349 | 447 sleep(5); |
pascal@12349 | 448 exit(1); |
pascal@12349 | 449 } |
pascal@12349 | 450 |
pascal@12273 | 451 static int main_ifmem(int argc, char *argv[]) |
pascal@12273 | 452 { |
pascal@12273 | 453 int i; |
pascal@12273 | 454 unsigned long ram_size; |
pascal@12273 | 455 |
pascal@12273 | 456 if (argc < 4) { |
pascal@12349 | 457 usage("Usage: ifmem.c32 size_KB boot_large_memory boot_small_memory"); |
pascal@12273 | 458 } |
pascal@12273 | 459 |
pascal@12273 | 460 // find target according to ram size |
pascal@12273 | 461 ram_size = memory_size(); |
pascal@12273 | 462 printf("Total memory found %luK.\n",ram_size); |
pascal@12273 | 463 ram_size += (1 << 10); // add 1M to round boundaries... |
pascal@12273 | 464 |
pascal@12273 | 465 i = 1; |
pascal@12273 | 466 do { |
pascal@12273 | 467 char *s = argv[i]; |
pascal@12273 | 468 char *p = s; |
pascal@12273 | 469 unsigned long scale = 1; |
pascal@12273 | 470 |
pascal@12273 | 471 while (*p >= '0' && *p <= '9') p++; |
pascal@12273 | 472 switch (*p | 0x20) { |
pascal@12273 | 473 case 'g': scale <<= 10; |
pascal@12273 | 474 case 'm': scale <<= 10; |
pascal@12273 | 475 default : *p = 0; break; |
pascal@12273 | 476 } |
pascal@12273 | 477 i++; // seek to label |
pascal@12273 | 478 if (ram_size >= scale * strtoul(s, NULL, 0)) break; |
pascal@12273 | 479 i++; // next size or default label |
pascal@12273 | 480 } while (i + 1 < argc); |
pascal@12273 | 481 |
pascal@12349 | 482 if (i != argc) syslinux_run_command(argv[i]); |
pascal@12273 | 483 else syslinux_run_default(); |
pascal@12273 | 484 return -1; |
pascal@12273 | 485 } |
pascal@12273 | 486 |
pascal@12273 | 487 #include <syslinux/reboot.h> |
pascal@12273 | 488 |
pascal@12273 | 489 static int main_reboot(int argc, char *argv[]) |
pascal@12273 | 490 { |
pascal@12273 | 491 int warm = 0; |
pascal@12273 | 492 int i; |
pascal@12273 | 493 |
pascal@12273 | 494 for (i = 1; i < argc; i++) { |
pascal@12273 | 495 if (!strcmp(argv[i], "-w") || !strcmp(argv[i], "--warm")) |
pascal@12273 | 496 warm = 1; |
pascal@12273 | 497 } |
pascal@12273 | 498 |
pascal@12273 | 499 syslinux_reboot(warm); |
pascal@12273 | 500 } |
pascal@12273 | 501 |
pascal@12273 | 502 /* APM poweroff module. |
pascal@12273 | 503 * based on poweroff.asm, Copyright 2009 Sebastian Herbszt |
pascal@12273 | 504 */ |
pascal@12273 | 505 |
pascal@12273 | 506 static int main_poweroff(int argc, char *argv[]) |
pascal@12273 | 507 { |
pascal@12273 | 508 static com32sys_t ireg, oreg; |
pascal@12273 | 509 static char notsupported[] ="APM 1.1+ not supported"; |
pascal@12273 | 510 unsigned i; |
pascal@12273 | 511 static struct { |
pascal@12273 | 512 unsigned short ax; |
pascal@12273 | 513 unsigned short bx; |
pascal@12273 | 514 unsigned short cx; |
pascal@12273 | 515 char *msg; |
pascal@12273 | 516 } inst[] = { |
pascal@12273 | 517 { 0x5300, // APM Installation Check (00h) |
pascal@12273 | 518 0, // APM BIOS (0000h) |
pascal@12273 | 519 0, "APM not present" }, |
pascal@12273 | 520 { 0x5301, // APM Real Mode Interface Connect (01h) |
pascal@12273 | 521 0, // APM BIOS (0000h) |
pascal@12273 | 522 0, "APM RM interface connect failed" }, |
pascal@12273 | 523 { 0x530E, // APM Driver Version (0Eh) |
pascal@12273 | 524 0, // APM BIOS (0000h) |
pascal@12273 | 525 0x0101, // APM Driver Version version 1.1 |
pascal@12273 | 526 notsupported }, |
pascal@12273 | 527 { 0x5307, // Set Power State (07h) |
pascal@12273 | 528 1, // All devices power managed by the APM |
pascal@12273 | 529 3, // Power state off |
pascal@12273 | 530 "Power off failed" } |
pascal@12273 | 531 }; |
pascal@12273 | 532 |
pascal@12273 | 533 (void) argc; |
pascal@12273 | 534 (void) argv; |
pascal@12273 | 535 for (i = 0; i < sizeof(inst)/sizeof(inst[0]); i++) { |
pascal@12273 | 536 char *msg = inst[i].msg; |
pascal@12273 | 537 |
pascal@12273 | 538 ireg.eax.w[0] = inst[i].ax; |
pascal@12273 | 539 ireg.ebx.w[0] = inst[i].bx; |
pascal@12273 | 540 ireg.ecx.w[0] = inst[i].cx; |
pascal@12273 | 541 __intcall(0x15, &ireg, &oreg); |
pascal@12273 | 542 if ((oreg.eflags.l & EFLAGS_CF) == 0) { |
pascal@12273 | 543 switch (inst[i].ax) { |
pascal@12273 | 544 case 0x5300 : |
pascal@12273 | 545 if (oreg.ebx.w[0] != 0x504D /* 'PM' */) break; |
pascal@12273 | 546 msg = "Power management disabled"; |
pascal@12273 | 547 if (oreg.ecx.w[0] & 8) break; // bit 3 APM BIOS Power Management disabled |
pascal@12273 | 548 case 0x530E : |
pascal@12273 | 549 msg = notsupported; |
pascal@12273 | 550 if (oreg.eax.w[0] < 0x101) break; |
pascal@12273 | 551 default : continue; |
pascal@12273 | 552 } |
pascal@12273 | 553 } |
pascal@12273 | 554 printf("%s.\n", msg); |
pascal@12273 | 555 return 1; |
pascal@12273 | 556 } |
pascal@12273 | 557 return 0; |
pascal@12273 | 558 } |
pascal@12273 | 559 |
pascal@12287 | 560 /* |
pascal@12287 | 561 * Copyright 2009 Intel Corporation; author: H. Peter Anvin |
pascal@12287 | 562 */ |
pascal@12287 | 563 |
pascal@12287 | 564 #include <syslinux/keyboard.h> |
pascal@12287 | 565 #include <syslinux/loadfile.h> |
pascal@12287 | 566 #include <syslinux/adv.h> |
pascal@12287 | 567 |
pascal@12349 | 568 static void setlinuxarg(int slot, int argc, char *argv[]) |
pascal@12349 | 569 { |
pascal@12349 | 570 for (; argc--; argv++) |
pascal@12349 | 571 syslinux_setadv(slot++, strlen(*argv), *argv); |
pascal@12349 | 572 } |
pascal@12349 | 573 |
pascal@12287 | 574 static int main_kbdmap(int argc, char *argv[]) |
pascal@12287 | 575 { |
pascal@12287 | 576 const struct syslinux_keyboard_map *const kmap = syslinux_keyboard_map(); |
pascal@12287 | 577 size_t map_size, size, i; |
pascal@12287 | 578 char *kbdmap, *msg; |
pascal@12287 | 579 |
pascal@12287 | 580 if (argc < 3) |
pascal@12349 | 581 usage("Usage: kbdmap archive.cpio mapfile [cmdline].."); |
pascal@12287 | 582 |
pascal@12293 | 583 // Save extra cmdline arguments |
pascal@12349 | 584 setlinuxarg(1, argc - 3, argv + 3); |
pascal@12293 | 585 |
pascal@13318 | 586 msg="Append to kernel parameters: "; |
pascal@13551 | 587 for (i = 3; i < (size_t) argc; i++, msg = " ") |
pascal@13318 | 588 printf("%s%s",msg,argv[i]); |
pascal@13318 | 589 printf("\n\n Hit RETURN to continue.\n"); |
pascal@13317 | 590 |
pascal@12287 | 591 msg = "Load error"; |
pascal@12287 | 592 if (kmap->version != 1 || |
pascal@12287 | 593 loadfile(argv[1], (void **) &kbdmap, &map_size) || |
pascal@12287 | 594 strncmp(kbdmap, "07070", 5)) |
pascal@12287 | 595 goto kbdmap_error; |
pascal@12287 | 596 |
pascal@12287 | 597 // search for mapfile in cpio archive |
pascal@12287 | 598 for (i = 0; i < map_size;) { |
pascal@12287 | 599 int len, j; |
pascal@12287 | 600 char *name; |
pascal@12287 | 601 |
pascal@12287 | 602 for (j = size = 0; j < 8; j++) { |
pascal@12287 | 603 char c = kbdmap[54 + i + j] - '0'; |
pascal@12287 | 604 if (c > 9) c += '0' + 10 - 'A'; |
pascal@12287 | 605 size <<= 4; |
pascal@12287 | 606 size += c; |
pascal@12287 | 607 } |
pascal@12287 | 608 i += 110; |
pascal@12287 | 609 name = kbdmap + i; |
pascal@12287 | 610 len = 1 + strlen(name); |
pascal@12287 | 611 i += len; |
pascal@12287 | 612 i += ((-i)&3); |
pascal@12287 | 613 if (!strcmp(name, argv[2])) { |
pascal@12287 | 614 kbdmap += i; |
pascal@12287 | 615 break; |
pascal@12287 | 616 } |
pascal@12287 | 617 i += size + ((-size)&3); |
pascal@12287 | 618 } |
pascal@12287 | 619 |
pascal@12287 | 620 msg = "Filename error"; |
pascal@12287 | 621 if (i >= map_size) |
pascal@12287 | 622 goto kbdmap_error; |
pascal@12287 | 623 |
pascal@12287 | 624 msg = "Format error"; |
pascal@12287 | 625 if (size != kmap->length) |
pascal@12287 | 626 goto kbdmap_error; |
pascal@12287 | 627 |
pascal@12287 | 628 memcpy(kmap->map, kbdmap, size); |
pascal@12287 | 629 |
pascal@12287 | 630 return 0; |
pascal@12287 | 631 |
pascal@12287 | 632 kbdmap_error: |
pascal@12287 | 633 printf("%s.\n",msg); |
pascal@12287 | 634 return 1; |
pascal@12287 | 635 } |
pascal@12287 | 636 |
pascal@12287 | 637 /* ----------------------------------------------------------------------- * |
pascal@12287 | 638 * |
pascal@12287 | 639 * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved |
pascal@13551 | 640 * Copyright 2009-2012 Intel Corporation; author: H. Peter Anvin |
pascal@12287 | 641 * |
pascal@12287 | 642 * Permission is hereby granted, free of charge, to any person |
pascal@12287 | 643 * obtaining a copy of this software and associated documentation |
pascal@12287 | 644 * files (the "Software"), to deal in the Software without |
pascal@12287 | 645 * restriction, including without limitation the rights to use, |
pascal@12287 | 646 * copy, modify, merge, publish, distribute, sublicense, and/or |
pascal@12287 | 647 * sell copies of the Software, and to permit persons to whom |
pascal@12287 | 648 * the Software is furnished to do so, subject to the following |
pascal@12287 | 649 * conditions: |
pascal@12287 | 650 * |
pascal@12287 | 651 * The above copyright notice and this permission notice shall |
pascal@12287 | 652 * be included in all copies or substantial portions of the Software. |
pascal@12287 | 653 * |
pascal@12287 | 654 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
pascal@12287 | 655 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
pascal@12287 | 656 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
pascal@12287 | 657 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
pascal@12287 | 658 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
pascal@12287 | 659 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
pascal@12287 | 660 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
pascal@12287 | 661 * OTHER DEALINGS IN THE SOFTWARE. |
pascal@12287 | 662 * |
pascal@12287 | 663 * ----------------------------------------------------------------------- */ |
pascal@12287 | 664 |
pascal@12287 | 665 /* |
pascal@12287 | 666 * linux.c |
pascal@12287 | 667 * |
pascal@12287 | 668 * Sample module to load Linux kernels. This module can also create |
pascal@12287 | 669 * a file out of the DHCP return data if running under PXELINUX. |
pascal@12287 | 670 * |
pascal@12287 | 671 * If -dhcpinfo is specified, the DHCP info is written into the file |
pascal@12287 | 672 * /dhcpinfo.dat in the initramfs. |
pascal@12287 | 673 * |
pascal@12287 | 674 * Usage: linux.c32 [-dhcpinfo] kernel arguments... |
pascal@12287 | 675 */ |
pascal@12287 | 676 |
pascal@13551 | 677 #include <errno.h> |
pascal@12287 | 678 #include <stdbool.h> |
pascal@12287 | 679 #include <stdlib.h> |
pascal@12287 | 680 #include <stdio.h> |
pascal@12287 | 681 #include <string.h> |
pascal@12287 | 682 #include <console.h> |
pascal@17057 | 683 #include <cpuid.h> |
pascal@12287 | 684 #include <syslinux/loadfile.h> |
pascal@12287 | 685 #include <syslinux/linux.h> |
pascal@12287 | 686 #include <syslinux/pxe.h> |
pascal@12287 | 687 |
pascal@12287 | 688 const char *progname = "linux.c32"; |
pascal@12287 | 689 |
pascal@12287 | 690 /* Find the last instance of a particular command line argument |
pascal@12287 | 691 (which should include the final =; do not use for boolean arguments) */ |
pascal@12287 | 692 static char *find_argument(char **argv, const char *argument) |
pascal@12287 | 693 { |
pascal@12287 | 694 int la = strlen(argument); |
pascal@12287 | 695 char **arg; |
pascal@12287 | 696 char *ptr = NULL; |
pascal@12287 | 697 |
pascal@12287 | 698 for (arg = argv; *arg; arg++) { |
pascal@12287 | 699 if (!memcmp(*arg, argument, la)) |
pascal@12287 | 700 ptr = *arg + la; |
pascal@12287 | 701 } |
pascal@12287 | 702 |
pascal@12287 | 703 return ptr; |
pascal@12287 | 704 } |
pascal@12287 | 705 |
pascal@12287 | 706 /* Search for a boolean argument; return its position, or 0 if not present */ |
pascal@12287 | 707 static int find_boolean(char **argv, const char *argument) |
pascal@12287 | 708 { |
pascal@12287 | 709 char **arg; |
pascal@12287 | 710 |
pascal@12287 | 711 for (arg = argv; *arg; arg++) { |
pascal@12287 | 712 if (!strcmp(*arg, argument)) |
pascal@12287 | 713 return (arg - argv) + 1; |
pascal@12287 | 714 } |
pascal@12287 | 715 |
pascal@12287 | 716 return 0; |
pascal@12287 | 717 } |
pascal@12287 | 718 |
pascal@12287 | 719 /* Stitch together the command line from a set of argv's */ |
pascal@12287 | 720 static char *make_cmdline(char **argv) |
pascal@12287 | 721 { |
pascal@12287 | 722 char **arg; |
pascal@13552 | 723 size_t bytes, size; |
pascal@12287 | 724 char *cmdline, *p; |
pascal@13552 | 725 int i; |
pascal@12287 | 726 |
pascal@12287 | 727 bytes = 1; /* Just in case we have a zero-entry cmdline */ |
pascal@12287 | 728 for (arg = argv; *arg; arg++) { |
pascal@12287 | 729 bytes += strlen(*arg) + 1; |
pascal@12287 | 730 } |
pascal@13552 | 731 for (i = 0; i < 255; i++) |
pascal@13552 | 732 if (syslinux_getadv(i, &size)) |
pascal@13552 | 733 bytes += ++size; |
pascal@13552 | 734 |
pascal@12287 | 735 p = cmdline = malloc(bytes); |
pascal@12287 | 736 if (!cmdline) |
pascal@12287 | 737 return NULL; |
pascal@12287 | 738 |
pascal@12287 | 739 for (arg = argv; *arg; arg++) { |
pascal@12287 | 740 int len = strlen(*arg); |
pascal@12287 | 741 memcpy(p, *arg, len); |
pascal@12287 | 742 p[len] = ' '; |
pascal@12287 | 743 p += len + 1; |
pascal@12287 | 744 } |
pascal@12287 | 745 |
pascal@13552 | 746 for (i = 0; i < 255; i++) { |
pascal@13552 | 747 const void *q = syslinux_getadv(i, &size); |
pascal@13552 | 748 if (q == NULL) continue; |
pascal@13552 | 749 memcpy(p, q, size); |
pascal@13552 | 750 p[size] = ' '; |
pascal@13552 | 751 p += size + 1; |
pascal@13552 | 752 } |
pascal@13552 | 753 |
pascal@12287 | 754 if (p > cmdline) |
pascal@12287 | 755 p--; /* Remove the last space */ |
pascal@12287 | 756 *p = '\0'; |
pascal@12287 | 757 |
pascal@12287 | 758 return cmdline; |
pascal@12287 | 759 } |
pascal@12287 | 760 |
pascal@17057 | 761 static bool __constfunc cpu_has_cpuid(void) |
pascal@17057 | 762 { |
pascal@17057 | 763 return cpu_has_eflag(X86_EFLAGS_ID); |
pascal@17057 | 764 } |
pascal@17057 | 765 |
pascal@17057 | 766 static bool __constfunc cpu_has_level(uint32_t level) |
pascal@17057 | 767 { |
pascal@17057 | 768 uint32_t group; |
pascal@17057 | 769 uint32_t limit; |
pascal@17057 | 770 |
pascal@17057 | 771 if (!cpu_has_cpuid()) |
pascal@17057 | 772 return false; |
pascal@17057 | 773 |
pascal@17057 | 774 group = level & 0xffff0000; |
pascal@17057 | 775 limit = cpuid_eax(group); |
pascal@17057 | 776 |
pascal@17057 | 777 if ((limit & 0xffff0000) != group) |
pascal@17057 | 778 return false; |
pascal@17057 | 779 |
pascal@17057 | 780 if (level > limit) |
pascal@17057 | 781 return false; |
pascal@17057 | 782 |
pascal@17057 | 783 return true; |
pascal@17057 | 784 } |
pascal@17057 | 785 |
pascal@17057 | 786 /* This only supports feature groups 0 and 1, corresponding to the |
pascal@17057 | 787 Intel and AMD EDX bit vectors. We can add more later if need be. */ |
pascal@17057 | 788 static bool __constfunc cpu_has_feature(int x) |
pascal@17057 | 789 { |
pascal@17057 | 790 uint32_t level = ((x & 1) << 31) | 1; |
pascal@17057 | 791 |
pascal@17057 | 792 return cpu_has_level(level) && ((cpuid_edx(level) >> (x & 31) & 1)); |
pascal@17057 | 793 } |
pascal@17057 | 794 |
pascal@17057 | 795 static char *extfilename(char *filename, char *ext, int feature) |
pascal@17057 | 796 { |
pascal@17060 | 797 #define NEWFILENAMESZ 256 |
pascal@17057 | 798 static char newfilename[NEWFILENAMESZ+1]; |
pascal@17057 | 799 char *found = filename; |
pascal@17060 | 800 char *new = newfilename; |
pascal@17060 | 801 int fd; |
pascal@17057 | 802 |
pascal@17057 | 803 if (strlen(filename) + strlen(ext) <= NEWFILENAMESZ) { |
pascal@17058 | 804 strcpy(newfilename, filename); |
pascal@17057 | 805 if (cpu_has_feature(feature)) { |
pascal@17057 | 806 strcat(newfilename, ext); |
pascal@17060 | 807 fd = open(new, O_RDONLY); |
pascal@17060 | 808 if (fd < 0) |
pascal@17060 | 809 fd = open(new = unrockridge(new), O_RDONLY); |
pascal@17060 | 810 if (fd >= 0) { |
pascal@17060 | 811 found = new; |
pascal@17060 | 812 close(fd); |
pascal@17060 | 813 } |
pascal@17057 | 814 } |
pascal@17057 | 815 } |
pascal@17057 | 816 return found; |
pascal@17057 | 817 } |
pascal@17057 | 818 |
pascal@17057 | 819 static char *bestextfilename(char *filename) |
pascal@17057 | 820 { |
pascal@17057 | 821 char *found; |
pascal@17057 | 822 |
pascal@17057 | 823 //found = extfilename(filename, "fpu", X86_FEATURE_FPU); |
pascal@17057 | 824 //found = extfilename(filename, "686", X86_FEATURE_CMOV); |
pascal@17057 | 825 //found = extfilename(filename, "pae", X86_FEATURE_PAE); |
pascal@17057 | 826 found = extfilename(filename, "64", X86_FEATURE_LM); |
pascal@17057 | 827 //found = extfilename(filename, "guest", X86_FEATURE_HYPERVISOR); |
pascal@17057 | 828 return found; |
pascal@17057 | 829 } |
pascal@17057 | 830 |
pascal@13551 | 831 static int setup_data_file(struct setup_data *setup_data, |
pascal@13551 | 832 uint32_t type, const char *filename, |
pascal@13551 | 833 bool opt_quiet) |
pascal@13551 | 834 { |
pascal@13551 | 835 if (!opt_quiet) |
pascal@13551 | 836 printf("Loading %s... ", filename); |
pascal@13551 | 837 |
pascal@13551 | 838 if (setup_data_load(setup_data, type, filename)) { |
pascal@13551 | 839 if (opt_quiet) |
pascal@13551 | 840 printf("Loading %s ", filename); |
pascal@13551 | 841 printf("failed\n"); |
pascal@13551 | 842 return -1; |
pascal@13551 | 843 } |
pascal@13551 | 844 |
pascal@13551 | 845 if (!opt_quiet) |
pascal@13551 | 846 printf("ok\n"); |
pascal@13551 | 847 |
pascal@13551 | 848 return 0; |
pascal@13551 | 849 } |
pascal@13551 | 850 |
pascal@12287 | 851 static int main_linux(int argc, char *argv[]) |
pascal@12287 | 852 { |
pascal@12287 | 853 const char *kernel_name; |
pascal@17057 | 854 const char *initrd_name; |
pascal@12287 | 855 struct initramfs *initramfs; |
pascal@13551 | 856 struct setup_data *setup_data; |
pascal@12287 | 857 char *cmdline; |
pascal@12287 | 858 char *boot_image; |
pascal@12287 | 859 void *kernel_data; |
pascal@12287 | 860 size_t kernel_len; |
pascal@12287 | 861 bool opt_dhcpinfo = false; |
pascal@12287 | 862 bool opt_quiet = false; |
pascal@12287 | 863 void *dhcpdata; |
pascal@12287 | 864 size_t dhcplen; |
pascal@13551 | 865 char **argp, **argl, *arg, *p; |
pascal@13551 | 866 |
pascal@13551 | 867 openconsole(&dev_null_r, &dev_stdcon_w); |
pascal@12287 | 868 |
pascal@12287 | 869 (void)argc; |
pascal@12287 | 870 argp = argv + 1; |
pascal@12287 | 871 |
pascal@12287 | 872 while ((arg = *argp) && arg[0] == '-') { |
pascal@12287 | 873 if (!strcmp("-dhcpinfo", arg)) { |
pascal@12287 | 874 opt_dhcpinfo = true; |
pascal@12287 | 875 } else { |
pascal@12287 | 876 fprintf(stderr, "%s: unknown option: %s\n", progname, arg); |
pascal@12287 | 877 return 1; |
pascal@12287 | 878 } |
pascal@12287 | 879 argp++; |
pascal@12287 | 880 } |
pascal@12287 | 881 |
pascal@12287 | 882 if (!arg) { |
pascal@12287 | 883 fprintf(stderr, "%s: missing kernel name\n", progname); |
pascal@12287 | 884 return 1; |
pascal@12287 | 885 } |
pascal@12287 | 886 |
pascal@17061 | 887 kernel_name = arg; |
pascal@12287 | 888 |
pascal@13551 | 889 errno = 0; |
pascal@12287 | 890 boot_image = malloc(strlen(kernel_name) + 12); |
pascal@13551 | 891 if (!boot_image) { |
pascal@13551 | 892 fprintf(stderr, "Error allocating BOOT_IMAGE string: "); |
pascal@12287 | 893 goto bail; |
pascal@13551 | 894 } |
pascal@12287 | 895 strcpy(boot_image, "BOOT_IMAGE="); |
pascal@12287 | 896 strcpy(boot_image + 11, kernel_name); |
pascal@12287 | 897 /* argp now points to the kernel name, and the command line follows. |
pascal@12287 | 898 Overwrite the kernel name with the BOOT_IMAGE= argument, and thus |
pascal@12287 | 899 we have the final argument. */ |
pascal@12287 | 900 *argp = boot_image; |
pascal@12287 | 901 |
pascal@12287 | 902 if (find_boolean(argp, "quiet")) |
pascal@12287 | 903 opt_quiet = true; |
pascal@12287 | 904 |
pascal@12287 | 905 if (!opt_quiet) |
pascal@12287 | 906 printf("Loading %s... ", kernel_name); |
pascal@13551 | 907 errno = 0; |
pascal@17061 | 908 if (loadfile(bestextfilename(kernel_name), &kernel_data, &kernel_len)) { |
pascal@12287 | 909 if (opt_quiet) |
pascal@12287 | 910 printf("Loading %s ", kernel_name); |
pascal@13551 | 911 printf("failed: "); |
pascal@12287 | 912 goto bail; |
pascal@12287 | 913 } |
pascal@12287 | 914 if (!opt_quiet) |
pascal@12287 | 915 printf("ok\n"); |
pascal@12287 | 916 |
pascal@13551 | 917 errno = 0; |
pascal@12287 | 918 cmdline = make_cmdline(argp); |
pascal@13551 | 919 if (!cmdline) { |
pascal@13551 | 920 fprintf(stderr, "make_cmdline() failed: "); |
pascal@12287 | 921 goto bail; |
pascal@13551 | 922 } |
pascal@12287 | 923 |
pascal@12287 | 924 /* Initialize the initramfs chain */ |
pascal@13551 | 925 errno = 0; |
pascal@12287 | 926 initramfs = initramfs_init(); |
pascal@13551 | 927 if (!initramfs) { |
pascal@13551 | 928 fprintf(stderr, "initramfs_init() failed: "); |
pascal@12287 | 929 goto bail; |
pascal@13551 | 930 } |
pascal@12287 | 931 |
pascal@12287 | 932 if ((arg = find_argument(argp, "initrd="))) { |
pascal@12287 | 933 do { |
pascal@12287 | 934 p = strchr(arg, ','); |
pascal@12287 | 935 if (p) |
pascal@12287 | 936 *p = '\0'; |
pascal@12287 | 937 |
pascal@17061 | 938 initrd_name = arg; |
pascal@12287 | 939 if (!opt_quiet) |
pascal@17057 | 940 printf("Loading %s... ", initrd_name); |
pascal@13551 | 941 errno = 0; |
pascal@17061 | 942 if (initramfs_load_archive(initramfs, bestextfilename(initrd_name))) { |
pascal@12287 | 943 if (opt_quiet) |
pascal@17057 | 944 printf("Loading %s ", initrd_name); |
pascal@13551 | 945 printf("failed: "); |
pascal@12287 | 946 goto bail; |
pascal@12287 | 947 } |
pascal@12287 | 948 if (!opt_quiet) |
pascal@12287 | 949 printf("ok\n"); |
pascal@12287 | 950 |
pascal@12287 | 951 if (p) |
pascal@12287 | 952 *p++ = ','; |
pascal@12287 | 953 } while ((arg = p)); |
pascal@12287 | 954 } |
pascal@12287 | 955 |
pascal@12287 | 956 /* Append the DHCP info */ |
pascal@12287 | 957 if (opt_dhcpinfo && |
pascal@12287 | 958 !pxe_get_cached_info(PXENV_PACKET_TYPE_DHCP_ACK, &dhcpdata, &dhcplen)) { |
pascal@13551 | 959 errno = 0; |
pascal@12287 | 960 if (initramfs_add_file(initramfs, dhcpdata, dhcplen, dhcplen, |
pascal@13551 | 961 "/dhcpinfo.dat", 0, 0755)) { |
pascal@13551 | 962 fprintf(stderr, "Unable to add DHCP info: "); |
pascal@12287 | 963 goto bail; |
pascal@13551 | 964 } |
pascal@13551 | 965 } |
pascal@13551 | 966 |
pascal@13551 | 967 /* Handle dtb and eventually other setup data */ |
pascal@13551 | 968 setup_data = setup_data_init(); |
pascal@13551 | 969 if (!setup_data) |
pascal@13551 | 970 goto bail; |
pascal@13551 | 971 |
pascal@13551 | 972 for (argl = argv; (arg = *argl); argl++) { |
pascal@13551 | 973 if (!memcmp(arg, "dtb=", 4)) { |
pascal@13551 | 974 if (setup_data_file(setup_data, SETUP_DTB, arg+4, opt_quiet)) |
pascal@13551 | 975 goto bail; |
pascal@13551 | 976 } else if (!memcmp(arg, "blob.", 5)) { |
pascal@13551 | 977 uint32_t type; |
pascal@13551 | 978 char *ep; |
pascal@13551 | 979 |
pascal@13551 | 980 type = strtoul(arg + 5, &ep, 10); |
pascal@13551 | 981 if (ep[0] != '=' || !ep[1]) |
pascal@13551 | 982 continue; |
pascal@13551 | 983 |
pascal@13551 | 984 if (!type) |
pascal@13551 | 985 continue; |
pascal@13551 | 986 |
pascal@13551 | 987 if (setup_data_file(setup_data, type, ep+1, opt_quiet)) |
pascal@13551 | 988 goto bail; |
pascal@13551 | 989 } |
pascal@12287 | 990 } |
pascal@12287 | 991 |
pascal@12287 | 992 /* This should not return... */ |
pascal@13551 | 993 errno = 0; |
pascal@13551 | 994 syslinux_boot_linux(kernel_data, kernel_len, initramfs, |
pascal@13551 | 995 setup_data, cmdline); |
pascal@13551 | 996 fprintf(stderr, "syslinux_boot_linux() failed: "); |
pascal@12287 | 997 |
pascal@12287 | 998 bail: |
pascal@13551 | 999 switch(errno) { |
pascal@13551 | 1000 case ENOENT: |
pascal@13551 | 1001 fprintf(stderr, "File not found\n"); |
pascal@13551 | 1002 break; |
pascal@13551 | 1003 case ENOMEM: |
pascal@13551 | 1004 fprintf(stderr, "Out of memory\n"); |
pascal@13551 | 1005 break; |
pascal@13551 | 1006 default: |
pascal@13551 | 1007 fprintf(stderr, "Error %d\n", errno); |
pascal@13551 | 1008 break; |
pascal@13551 | 1009 } |
pascal@13551 | 1010 fprintf(stderr, "%s: Boot aborted!\n", progname); |
pascal@12287 | 1011 return 1; |
pascal@12287 | 1012 } |
pascal@12287 | 1013 |
pascal@12349 | 1014 static int main_setarg(int argc, char *argv[]) |
pascal@12349 | 1015 { |
pascal@12349 | 1016 if (argc < 3) { |
pascal@12349 | 1017 usage("Usage: setarg.c32 argnum [args]..."); |
pascal@12349 | 1018 } |
pascal@12349 | 1019 setlinuxarg(atoi(argv[1]), argc - 2, argv + 2); |
pascal@12349 | 1020 return 0; |
pascal@12349 | 1021 } |
pascal@12349 | 1022 |
pascal@12349 | 1023 static int main_ifarg(int argc, char *argv[]) |
pascal@12349 | 1024 { |
pascal@12349 | 1025 int i; |
pascal@12349 | 1026 size_t size; |
pascal@12349 | 1027 |
pascal@12349 | 1028 if (argc < 3) { |
pascal@12349 | 1029 usage("Usage: ifarg.c32 [argnum labelifset]... labelifnoneset"); |
pascal@12349 | 1030 } |
pascal@12349 | 1031 for (i = 1; i < argc - 1; i += 2) { |
pascal@13295 | 1032 int n = atoi(argv[i]); |
pascal@13295 | 1033 if (n == -1) { |
pascal@13295 | 1034 for (n = 0; n < 255; n++) { |
pascal@13316 | 1035 if (syslinux_getadv(n, &size)) |
pascal@13295 | 1036 goto found; |
pascal@13295 | 1037 } |
pascal@13295 | 1038 continue; |
pascal@13295 | 1039 } |
pascal@13295 | 1040 else if (! syslinux_getadv(n, &size)) continue; |
pascal@13295 | 1041 found: |
pascal@13295 | 1042 syslinux_run_command(argv[i+1]); |
pascal@12349 | 1043 } |
pascal@12349 | 1044 if (i != argc) syslinux_run_command(argv[i]); |
pascal@12349 | 1045 else syslinux_run_default(); |
pascal@12349 | 1046 return 0; |
pascal@12349 | 1047 } |
pascal@12349 | 1048 |
pascal@12349 | 1049 /* ----------------------------------------------------------------------- * |
pascal@12349 | 1050 * |
pascal@12349 | 1051 * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved |
pascal@12349 | 1052 * |
pascal@12349 | 1053 * This program is free software; you can redistribute it and/or modify |
pascal@12349 | 1054 * it under the terms of the GNU General Public License as published by |
pascal@12349 | 1055 * the Free Software Foundation, Inc., 53 Temple Place Ste 330, |
pascal@12349 | 1056 * Boston MA 02111-1307, USA; either version 2 of the License, or |
pascal@12349 | 1057 * (at your option) any later version; incorporated herein by reference. |
pascal@12349 | 1058 * |
pascal@12349 | 1059 * ----------------------------------------------------------------------- */ |
pascal@12349 | 1060 |
pascal@12349 | 1061 static int main_listarg(int argc, char *argv[]) |
pascal@12349 | 1062 { |
pascal@12349 | 1063 uint8_t *p, *ep; |
pascal@12349 | 1064 size_t s = syslinux_adv_size(); |
pascal@12349 | 1065 char buf[256]; |
pascal@12349 | 1066 |
pascal@12349 | 1067 (void) argc; |
pascal@12349 | 1068 (void) argv; |
pascal@12349 | 1069 p = syslinux_adv_ptr(); |
pascal@12349 | 1070 |
pascal@12349 | 1071 printf("args size: %zd bytes at %p\n", s, p); |
pascal@12349 | 1072 |
pascal@12349 | 1073 ep = p + s; /* Need at least opcode+len */ |
pascal@12349 | 1074 while (p < ep - 1 && *p) { |
pascal@12349 | 1075 int t = *p++; |
pascal@12349 | 1076 int l = *p++; |
pascal@12349 | 1077 |
pascal@12349 | 1078 if (p + l > ep) |
pascal@12349 | 1079 break; |
pascal@12349 | 1080 |
pascal@12349 | 1081 memcpy(buf, p, l); |
pascal@12349 | 1082 buf[l] = '\0'; |
pascal@12349 | 1083 |
pascal@12349 | 1084 printf("arg %3d: \"%s\"\n", t, buf); |
pascal@12349 | 1085 |
pascal@12349 | 1086 p += l; |
pascal@12349 | 1087 } |
pascal@12349 | 1088 sleep(5); |
pascal@12349 | 1089 return 0; |
pascal@12349 | 1090 } |
pascal@12349 | 1091 |
pascal@12273 | 1092 int main(int argc, char *argv[]) |
pascal@12273 | 1093 { |
pascal@12273 | 1094 unsigned i; |
pascal@12273 | 1095 static struct { |
pascal@12273 | 1096 char *name; |
pascal@12273 | 1097 int (*main)(int argc, char *argv[]); |
pascal@12273 | 1098 } bin[] = { |
pascal@13295 | 1099 { "say", main_say }, |
pascal@13295 | 1100 { "md5sum", main_md5sum }, |
pascal@13295 | 1101 { "ifmem", main_ifmem }, |
pascal@13295 | 1102 { "reboot", main_reboot }, |
pascal@12287 | 1103 { "poweroff", main_poweroff }, |
pascal@13295 | 1104 { "kbdmap", main_kbdmap }, |
pascal@13295 | 1105 { "linux", main_linux }, |
pascal@13295 | 1106 { "setarg", main_setarg }, |
pascal@13295 | 1107 { "ifarg", main_ifarg }, |
pascal@13295 | 1108 { "listarg", main_listarg } |
pascal@12273 | 1109 }; |
pascal@12273 | 1110 |
pascal@12273 | 1111 openconsole(&dev_null_r, &dev_stdcon_w); |
pascal@12273 | 1112 |
pascal@12273 | 1113 if (strstr(argv[0], "c32box")) { argc--; argv++; } |
pascal@12273 | 1114 for (i = 0; i < sizeof(bin)/sizeof(bin[0]); i++) |
pascal@12273 | 1115 if (strstr(argv[0], bin[i].name)) |
pascal@12273 | 1116 return bin[i].main(argc, argv); |
pascal@12287 | 1117 printf("No %s in c32box modules\n", argv[0]); |
pascal@12287 | 1118 for (i = 0; i < sizeof(bin)/sizeof(bin[0]); i++) |
pascal@12287 | 1119 printf(" %s \n",bin[i].name); |
pascal@12273 | 1120 return 1; |
pascal@12273 | 1121 } |