rev |
line source |
pascal@3665
|
1 /* ----------------------------------------------------------------------- *
|
pascal@3665
|
2 *
|
pascal@3665
|
3 * Copyright 2009 Pascal Bellard - All Rights Reserved
|
pascal@3665
|
4 *
|
pascal@3665
|
5 * This program is free software; you can redistribute it and/or modify
|
pascal@3665
|
6 * it under the terms of the GNU General Public License as published by
|
pascal@3665
|
7 * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
pascal@3665
|
8 * Boston MA 02110-1301, USA; either version 2 of the License, or
|
pascal@3665
|
9 * (at your option) any later version; incorporated herein by reference.
|
pascal@3665
|
10 *
|
pascal@3665
|
11 * ----------------------------------------------------------------------- */
|
pascal@3665
|
12
|
pascal@3665
|
13 /*
|
pascal@3665
|
14 * ifmem.c
|
pascal@3665
|
15 *
|
pascal@3665
|
16 * Run one command if the memory is large enought, and another if it isn't.
|
pascal@3665
|
17 *
|
pascal@3665
|
18 * Usage:
|
pascal@3665
|
19 *
|
pascal@3665
|
20 * label boot_kernel
|
pascal@3665
|
21 * kernel ifmem.c
|
pascal@3665
|
22 * append size_in_KB boot_large [size_in_KB boot_medium] boot_small
|
pascal@3665
|
23 *
|
pascal@3665
|
24 * label boot_large
|
pascal@3665
|
25 * kernel vmlinuz_large_memory
|
pascal@3665
|
26 * append ...
|
pascal@3665
|
27 *
|
pascal@3665
|
28 * label boot_small
|
pascal@3665
|
29 * kernel vmlinuz_small_memory
|
pascal@3665
|
30 * append ...
|
pascal@3665
|
31 */
|
pascal@3665
|
32
|
pascal@3665
|
33 #include <inttypes.h>
|
pascal@3665
|
34 #include <com32.h>
|
pascal@3665
|
35 #include <console.h>
|
pascal@3665
|
36 #include <stdio.h>
|
pascal@3665
|
37 #include <string.h>
|
pascal@3665
|
38 #include <alloca.h>
|
pascal@3665
|
39 #include <stdlib.h>
|
pascal@3665
|
40 #include <syslinux/boot.h>
|
pascal@3665
|
41
|
pascal@3918
|
42 struct e820_data {
|
pascal@12216
|
43 uint64_t base;
|
pascal@12216
|
44 uint64_t len;
|
pascal@12216
|
45 uint32_t type;
|
pascal@12216
|
46 uint32_t extattr;
|
pascal@3918
|
47 } __attribute__((packed));
|
pascal@3918
|
48
|
pascal@3918
|
49 // Get memory size in Kb
|
pascal@3867
|
50 static unsigned long memory_size(void)
|
pascal@3665
|
51 {
|
pascal@12216
|
52 uint64_t bytes = 0;
|
pascal@12216
|
53 static com32sys_t ireg, oreg;
|
pascal@12216
|
54 static struct e820_data ed;
|
pascal@3665
|
55
|
pascal@12216
|
56 ireg.eax.w[0] = 0xe820;
|
pascal@12216
|
57 ireg.edx.l = 0x534d4150;
|
pascal@12216
|
58 ireg.ecx.l = sizeof(struct e820_data);
|
pascal@12216
|
59 ireg.edi.w[0] = OFFS(__com32.cs_bounce);
|
pascal@12216
|
60 ireg.es = SEG(__com32.cs_bounce);
|
pascal@3665
|
61
|
pascal@12216
|
62 ed.extattr = 1;
|
pascal@3665
|
63
|
pascal@12216
|
64 do {
|
pascal@12216
|
65 memcpy(__com32.cs_bounce, &ed, sizeof ed);
|
pascal@3918
|
66
|
pascal@12216
|
67 __intcall(0x15, &ireg, &oreg);
|
pascal@12216
|
68 if (oreg.eflags.l & EFLAGS_CF ||
|
pascal@12216
|
69 oreg.eax.l != 0x534d4150 ||
|
pascal@12216
|
70 oreg.ecx.l < 20)
|
pascal@12216
|
71 break;
|
pascal@3918
|
72
|
pascal@12216
|
73 memcpy(&ed, __com32.cs_bounce, sizeof ed);
|
pascal@3918
|
74
|
pascal@12216
|
75 if (ed.type == 1)
|
pascal@12216
|
76 bytes += ed.len;
|
pascal@3918
|
77
|
pascal@12216
|
78 ireg.ebx.l = oreg.ebx.l;
|
pascal@12216
|
79 } while (ireg.ebx.l);
|
pascal@3918
|
80
|
pascal@12216
|
81 if (!bytes) {
|
pascal@12216
|
82 memset(&ireg, 0, sizeof ireg);
|
pascal@12216
|
83 ireg.eax.w[0] = 0x8800;
|
pascal@12216
|
84 __intcall(0x15, &ireg, &oreg);
|
pascal@12216
|
85 return ireg.eax.w[0];
|
pascal@12216
|
86 }
|
pascal@12216
|
87 return bytes >> 10;
|
pascal@3665
|
88 }
|
pascal@3665
|
89
|
pascal@3665
|
90 int main(int argc, char *argv[])
|
pascal@3665
|
91 {
|
pascal@12216
|
92 int i;
|
pascal@12216
|
93 unsigned long ram_size;
|
pascal@3665
|
94
|
pascal@12216
|
95 openconsole(&dev_null_r, &dev_stdcon_w);
|
pascal@10876
|
96
|
pascal@12216
|
97 if (argc < 4) {
|
pascal@12216
|
98 perror("\nUsage: ifmem.c32 size_KB boot_large_memory boot_small_memory\n");
|
pascal@12216
|
99 return 1;
|
pascal@12216
|
100 }
|
pascal@3665
|
101
|
pascal@12216
|
102 // find target according to ram size
|
pascal@12216
|
103 ram_size = memory_size();
|
pascal@12216
|
104 printf("Total memory found %luK.\n",ram_size);
|
pascal@12216
|
105 ram_size += (1 << 10); // add 1M to round boundaries...
|
pascal@10876
|
106
|
pascal@12216
|
107 i = 1;
|
pascal@12216
|
108 do {
|
pascal@12216
|
109 char *s = argv[i];
|
pascal@12216
|
110 char *p = s;
|
pascal@12216
|
111 unsigned long scale = 1;
|
pascal@3867
|
112
|
pascal@12216
|
113 while (*p >= '0' && *p <= '9') p++;
|
pascal@12216
|
114 switch (*p | 0x20) {
|
pascal@12216
|
115 case 'g': scale <<= 10;
|
pascal@12216
|
116 case 'm': scale <<= 10;
|
pascal@12216
|
117 default : *p = 0; break;
|
pascal@12216
|
118 }
|
pascal@12216
|
119 i++; // seek to label
|
pascal@12216
|
120 if (ram_size >= scale * strtoul(s, NULL, 0)) break;
|
pascal@12216
|
121 i++; // next size or default label
|
pascal@12216
|
122 } while (i + 1 < argc);
|
pascal@12216
|
123
|
pascal@12216
|
124 if (i != argc) syslinux_run_command(argv[i]);
|
pascal@12216
|
125 else syslinux_run_default();
|
pascal@12216
|
126 return -1;
|
pascal@3665
|
127 }
|