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@3918
|
43 uint64_t base;
|
pascal@3918
|
44 uint64_t len;
|
pascal@3918
|
45 uint32_t type;
|
pascal@3918
|
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@3922
|
52 uint64_t bytes = 0;
|
pascal@3665
|
53 com32sys_t ireg, oreg;
|
pascal@3918
|
54 struct e820_data ed;
|
pascal@3665
|
55
|
pascal@3665
|
56 memset(&ireg, 0, sizeof ireg);
|
pascal@3665
|
57
|
pascal@3918
|
58 ireg.eax.w[0] = 0xe820;
|
pascal@3918
|
59 ireg.edx.l = 0x534d4150;
|
pascal@3918
|
60 ireg.ecx.l = sizeof(struct e820_data);
|
pascal@3918
|
61 ireg.edi.w[0] = OFFS(__com32.cs_bounce);
|
pascal@3918
|
62 ireg.es = SEG(__com32.cs_bounce);
|
pascal@3665
|
63
|
pascal@3918
|
64 memset(&ed, 0, sizeof ed);
|
pascal@3918
|
65 ed.extattr = 1;
|
pascal@3918
|
66
|
pascal@3918
|
67 do {
|
pascal@3918
|
68 memcpy(__com32.cs_bounce, &ed, sizeof ed);
|
pascal@3918
|
69
|
pascal@3918
|
70 __intcall(0x15, &ireg, &oreg);
|
pascal@3918
|
71 if (oreg.eflags.l & EFLAGS_CF ||
|
pascal@3918
|
72 oreg.eax.l != 0x534d4150 ||
|
pascal@3918
|
73 oreg.ecx.l < 20)
|
pascal@3918
|
74 break;
|
pascal@3918
|
75
|
pascal@3918
|
76 memcpy(&ed, __com32.cs_bounce, sizeof ed);
|
pascal@3918
|
77
|
pascal@3918
|
78 if (ed.type == 1)
|
pascal@3918
|
79 bytes += ed.len;
|
pascal@3918
|
80
|
pascal@3918
|
81 ireg.ebx.l = oreg.ebx.l;
|
pascal@3918
|
82 } while (ireg.ebx.l);
|
pascal@3918
|
83
|
pascal@3918
|
84 if (!bytes) {
|
pascal@3918
|
85 memset(&ireg, 0, sizeof ireg);
|
pascal@3918
|
86 ireg.eax.w[0] = 0x8800;
|
pascal@3918
|
87 __intcall(0x15, &ireg, &oreg);
|
pascal@3918
|
88 return ireg.eax.w[0];
|
pascal@3917
|
89 }
|
pascal@3918
|
90 return bytes / 1024;
|
pascal@3665
|
91 }
|
pascal@3665
|
92
|
pascal@3665
|
93 int main(int argc, char *argv[])
|
pascal@3665
|
94 {
|
pascal@3665
|
95 char *s;
|
pascal@3870
|
96 int i, j = 1;
|
pascal@3922
|
97 unsigned long ram_size;
|
pascal@3665
|
98
|
pascal@3665
|
99 for (s = argv[1]; *s && (*s < '0' || *s > '9'); s++);
|
pascal@3665
|
100
|
pascal@3922
|
101 openconsole(&dev_null_r, &dev_stdcon_w);
|
pascal@3665
|
102 if (argc < 4 || !*s) {
|
pascal@3665
|
103 perror("\nUsage: ifmem.c32 size_KB boot_large_memory boot_small_memory\n");
|
pascal@3665
|
104 return 1;
|
pascal@3665
|
105 }
|
pascal@3665
|
106
|
pascal@3868
|
107 // find target according to ram size
|
pascal@3922
|
108 ram_size = memory_size();
|
pascal@3922
|
109 printf("Total memory found %luK.\n",ram_size);
|
pascal@3665
|
110 for (i = 1; i + 2 < argc; ) {
|
pascal@4345
|
111 char *p = s;
|
pascal@4345
|
112 unsigned long scale = 1;
|
pascal@4345
|
113
|
pascal@4345
|
114 if (*p) while (p[1]) p++;
|
pascal@4345
|
115 switch (*p | 0x20) {
|
pascal@4345
|
116 case 'g': scale = 1024*1024; *p = 0; break;
|
pascal@4345
|
117 case 'm': scale = 1024;
|
pascal@4345
|
118 case 'k': *p = 0; break;
|
pascal@4345
|
119 }
|
pascal@3869
|
120 j = i++; // size
|
pascal@4345
|
121 if (ram_size >= scale * strtoul(s, NULL, 0)) break;
|
pascal@3665
|
122 s = argv[++i];
|
pascal@3665
|
123 }
|
pascal@3867
|
124
|
pascal@3868
|
125 // find and copy extra parameters to command line
|
pascal@3869
|
126 // assume the command line ends with two words (not number)
|
pascal@3869
|
127 for (s = argv[i++]; i < argc; i++) {
|
pascal@3870
|
128 char c = *argv[i];
|
pascal@3869
|
129 if (c >= '0' && c <= '9') j = i;
|
pascal@3870
|
130 if (i - j > 2 && i < argc) {
|
pascal@4345
|
131 #define SZ 4096
|
pascal@3867
|
132 static char cmdline[SZ];
|
pascal@3867
|
133 char *p = cmdline, *q = s;
|
pascal@3867
|
134 int j;
|
pascal@3867
|
135 for (j = i; j <= argc; j++) {
|
pascal@3867
|
136 while (*q && p < cmdline + SZ -1) *p++ = *q++;
|
pascal@3867
|
137 if (p < cmdline + SZ -1) *p++ = ' ';
|
pascal@3867
|
138 q = argv[j];
|
pascal@3867
|
139 }
|
pascal@3867
|
140 *p++ = 0;
|
pascal@3867
|
141 s = cmdline;
|
pascal@4346
|
142 break;
|
pascal@3867
|
143 }
|
pascal@3867
|
144 }
|
pascal@3867
|
145
|
pascal@3867
|
146 if (s) syslinux_run_command(s);
|
pascal@3867
|
147 else syslinux_run_default();
|
pascal@3665
|
148 return -1;
|
pascal@3665
|
149 }
|