]>
Commit | Line | Data |
---|---|---|
b1b797cb | 1 | /* minicmd.c - commands for the rescue mode */ |
2 | /* | |
3 | * GRUB -- GRand Unified Bootloader | |
0d5d5653 | 4 | * Copyright (C) 2003,2005,2006,2007,2009 Free Software Foundation, Inc. |
b1b797cb | 5 | * |
6 | * GRUB is free software: you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License as published by | |
8 | * the Free Software Foundation, either version 3 of the License, or | |
9 | * (at your option) any later version. | |
10 | * | |
11 | * GRUB is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | * GNU General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * along with GRUB. If not, see <http://www.gnu.org/licenses/>. | |
18 | */ | |
19 | ||
20 | #include <grub/dl.h> | |
21 | #include <grub/mm.h> | |
22 | #include <grub/err.h> | |
23 | #include <grub/env.h> | |
24 | #include <grub/misc.h> | |
25 | #include <grub/file.h> | |
26 | #include <grub/disk.h> | |
27 | #include <grub/term.h> | |
28 | #include <grub/loader.h> | |
29 | #include <grub/command.h> | |
77a79592 | 30 | #include <grub/i18n.h> |
b1b797cb | 31 | |
b1b797cb | 32 | /* cat FILE */ |
33 | static grub_err_t | |
34 | grub_mini_cmd_cat (struct grub_command *cmd __attribute__ ((unused)), | |
35 | int argc, char *argv[]) | |
36 | { | |
37 | grub_file_t file; | |
38 | char buf[GRUB_DISK_SECTOR_SIZE]; | |
39 | grub_ssize_t size; | |
40 | ||
41 | if (argc < 1) | |
42 | return grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified"); | |
43 | ||
44 | file = grub_file_open (argv[0]); | |
45 | if (! file) | |
46 | return grub_errno; | |
47 | ||
48 | while ((size = grub_file_read (file, buf, sizeof (buf))) > 0) | |
49 | { | |
50 | int i; | |
51 | ||
52 | for (i = 0; i < size; i++) | |
53 | { | |
54 | unsigned char c = buf[i]; | |
55 | ||
56 | if ((grub_isprint (c) || grub_isspace (c)) && c != '\r') | |
dfed5c6b | 57 | grub_printf ("%c", c); |
b1b797cb | 58 | else |
59 | { | |
60 | grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT); | |
61 | grub_printf ("<%x>", (int) c); | |
62 | grub_setcolorstate (GRUB_TERM_COLOR_STANDARD); | |
63 | } | |
64 | } | |
65 | } | |
66 | ||
dfed5c6b | 67 | grub_xputs ("\n"); |
b1b797cb | 68 | grub_refresh (); |
69 | grub_file_close (file); | |
70 | ||
71 | return 0; | |
72 | } | |
73 | ||
74 | /* help */ | |
75 | static grub_err_t | |
76 | grub_mini_cmd_help (struct grub_command *cmd __attribute__ ((unused)), | |
77 | int argc __attribute__ ((unused)), | |
78 | char *argv[] __attribute__ ((unused))) | |
79 | { | |
80 | grub_command_t p; | |
81 | ||
82 | for (p = grub_command_list; p; p = p->next) | |
83 | grub_printf ("%s (%d%c)\t%s\n", p->name, | |
84 | p->prio & GRUB_PRIO_LIST_PRIO_MASK, | |
85 | (p->prio & GRUB_PRIO_LIST_FLAG_ACTIVE) ? '+' : '-', | |
86 | p->description); | |
87 | ||
88 | return 0; | |
89 | } | |
90 | ||
91 | #if 0 | |
92 | static void | |
93 | grub_rescue_cmd_info (void) | |
94 | { | |
95 | extern void grub_disk_cache_get_performance (unsigned long *, | |
96 | unsigned long *); | |
97 | unsigned long hits, misses; | |
98 | ||
99 | grub_disk_cache_get_performance (&hits, &misses); | |
100 | grub_printf ("Disk cache: hits = %u, misses = %u ", hits, misses); | |
101 | if (hits + misses) | |
102 | { | |
103 | unsigned long ratio = hits * 10000 / (hits + misses); | |
104 | grub_printf ("(%u.%u%%)\n", ratio / 100, ratio % 100); | |
105 | } | |
106 | else | |
107 | grub_printf ("(N/A)\n"); | |
108 | } | |
109 | #endif | |
110 | ||
111 | /* root [DEVICE] */ | |
112 | static grub_err_t | |
113 | grub_mini_cmd_root (struct grub_command *cmd __attribute__ ((unused)), | |
114 | int argc, char *argv[]) | |
115 | { | |
116 | grub_device_t dev; | |
117 | grub_fs_t fs; | |
118 | ||
119 | if (argc > 0) | |
120 | { | |
121 | char *device_name = grub_file_get_device_name (argv[0]); | |
122 | if (! device_name) | |
123 | return grub_errno; | |
124 | ||
125 | grub_env_set ("root", device_name); | |
126 | grub_free (device_name); | |
127 | } | |
128 | ||
129 | dev = grub_device_open (0); | |
130 | if (! dev) | |
131 | return grub_errno; | |
132 | ||
133 | fs = grub_fs_probe (dev); | |
134 | if (grub_errno == GRUB_ERR_UNKNOWN_FS) | |
135 | grub_errno = GRUB_ERR_NONE; | |
136 | ||
137 | grub_printf ("(%s): Filesystem is %s.\n", | |
138 | grub_env_get ("root"), fs ? fs->name : "unknown"); | |
139 | ||
140 | grub_device_close (dev); | |
141 | ||
142 | return 0; | |
143 | } | |
144 | ||
145 | #if 0 | |
146 | static void | |
147 | grub_rescue_cmd_testload (int argc, char *argv[]) | |
148 | { | |
149 | grub_file_t file; | |
150 | char *buf; | |
151 | grub_ssize_t size; | |
152 | grub_ssize_t pos; | |
153 | auto void read_func (unsigned long sector, unsigned offset, unsigned len); | |
154 | ||
155 | void read_func (unsigned long sector __attribute__ ((unused)), | |
156 | unsigned offset __attribute__ ((unused)), | |
157 | unsigned len __attribute__ ((unused))) | |
158 | { | |
159 | grub_putchar ('.'); | |
160 | grub_refresh (); | |
161 | } | |
162 | ||
163 | if (argc < 1) | |
164 | { | |
165 | grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified"); | |
166 | return; | |
167 | } | |
168 | ||
169 | file = grub_file_open (argv[0]); | |
170 | if (! file) | |
171 | return; | |
172 | ||
173 | size = grub_file_size (file) & ~(GRUB_DISK_SECTOR_SIZE - 1); | |
174 | if (size == 0) | |
175 | { | |
176 | grub_file_close (file); | |
177 | return; | |
178 | } | |
179 | ||
180 | buf = grub_malloc (size); | |
181 | if (! buf) | |
182 | goto fail; | |
183 | ||
184 | grub_printf ("Reading %s sequentially", argv[0]); | |
185 | file->read_hook = read_func; | |
186 | if (grub_file_read (file, buf, size) != size) | |
187 | goto fail; | |
188 | grub_printf (" Done.\n"); | |
189 | ||
190 | /* Read sequentially again. */ | |
191 | grub_printf ("Reading %s sequentially again", argv[0]); | |
192 | if (grub_file_seek (file, 0) < 0) | |
193 | goto fail; | |
194 | ||
195 | for (pos = 0; pos < size; pos += GRUB_DISK_SECTOR_SIZE) | |
196 | { | |
197 | char sector[GRUB_DISK_SECTOR_SIZE]; | |
198 | ||
199 | if (grub_file_read (file, sector, GRUB_DISK_SECTOR_SIZE) | |
200 | != GRUB_DISK_SECTOR_SIZE) | |
201 | goto fail; | |
202 | ||
203 | if (grub_memcmp (sector, buf + pos, GRUB_DISK_SECTOR_SIZE) != 0) | |
204 | { | |
205 | grub_printf ("\nDiffers in %d\n", pos); | |
206 | goto fail; | |
207 | } | |
208 | } | |
209 | grub_printf (" Done.\n"); | |
210 | ||
211 | /* Read backwards and compare. */ | |
212 | grub_printf ("Reading %s backwards", argv[0]); | |
213 | pos = size; | |
214 | while (pos > 0) | |
215 | { | |
216 | char sector[GRUB_DISK_SECTOR_SIZE]; | |
217 | ||
218 | pos -= GRUB_DISK_SECTOR_SIZE; | |
219 | ||
220 | if (grub_file_seek (file, pos) < 0) | |
221 | goto fail; | |
222 | ||
223 | if (grub_file_read (file, sector, GRUB_DISK_SECTOR_SIZE) | |
224 | != GRUB_DISK_SECTOR_SIZE) | |
225 | goto fail; | |
226 | ||
227 | if (grub_memcmp (sector, buf + pos, GRUB_DISK_SECTOR_SIZE) != 0) | |
228 | { | |
229 | int i; | |
230 | ||
231 | grub_printf ("\nDiffers in %d\n", pos); | |
232 | ||
233 | for (i = 0; i < GRUB_DISK_SECTOR_SIZE; i++) | |
234 | grub_putchar (buf[pos + i]); | |
235 | ||
236 | if (i) | |
237 | grub_refresh (); | |
238 | ||
239 | goto fail; | |
240 | } | |
241 | } | |
242 | grub_printf (" Done.\n"); | |
243 | ||
244 | fail: | |
245 | ||
246 | grub_file_close (file); | |
247 | grub_free (buf); | |
248 | } | |
249 | #endif | |
250 | ||
251 | /* dump ADDRESS [SIZE] */ | |
252 | static grub_err_t | |
253 | grub_mini_cmd_dump (struct grub_command *cmd __attribute__ ((unused)), | |
254 | int argc, char *argv[]) | |
255 | { | |
256 | grub_uint8_t *addr; | |
257 | grub_size_t size = 4; | |
258 | ||
259 | if (argc == 0) | |
260 | return grub_error (GRUB_ERR_BAD_ARGUMENT, "no address specified"); | |
261 | ||
262 | addr = (grub_uint8_t *) grub_strtoul (argv[0], 0, 0); | |
263 | if (grub_errno) | |
264 | return grub_errno; | |
265 | ||
266 | if (argc > 1) | |
267 | size = (grub_size_t) grub_strtoul (argv[1], 0, 0); | |
268 | ||
269 | while (size--) | |
270 | { | |
271 | grub_printf ("%x%x ", *addr >> 4, *addr & 0xf); | |
272 | addr++; | |
273 | } | |
274 | ||
275 | return 0; | |
276 | } | |
277 | ||
278 | /* rmmod MODULE */ | |
279 | static grub_err_t | |
280 | grub_mini_cmd_rmmod (struct grub_command *cmd __attribute__ ((unused)), | |
281 | int argc, char *argv[]) | |
282 | { | |
283 | grub_dl_t mod; | |
284 | ||
285 | if (argc == 0) | |
286 | return grub_error (GRUB_ERR_BAD_ARGUMENT, "no module specified"); | |
287 | ||
288 | mod = grub_dl_get (argv[0]); | |
289 | if (! mod) | |
290 | return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such module"); | |
291 | ||
292 | if (grub_dl_unref (mod) <= 0) | |
293 | grub_dl_unload (mod); | |
294 | ||
295 | return 0; | |
296 | } | |
297 | ||
298 | /* lsmod */ | |
299 | static grub_err_t | |
300 | grub_mini_cmd_lsmod (struct grub_command *cmd __attribute__ ((unused)), | |
301 | int argc __attribute__ ((unused)), | |
302 | char *argv[] __attribute__ ((unused))) | |
303 | { | |
304 | auto int print_module (grub_dl_t mod); | |
305 | ||
306 | int print_module (grub_dl_t mod) | |
307 | { | |
308 | grub_dl_dep_t dep; | |
309 | ||
310 | grub_printf ("%s\t%d\t\t", mod->name, mod->ref_count); | |
311 | for (dep = mod->dep; dep; dep = dep->next) | |
312 | { | |
313 | if (dep != mod->dep) | |
dfed5c6b | 314 | grub_xputs (","); |
b1b797cb | 315 | |
316 | grub_printf ("%s", dep->mod->name); | |
317 | } | |
dfed5c6b | 318 | grub_xputs ("\n"); |
b1b797cb | 319 | |
320 | return 0; | |
321 | } | |
322 | ||
323 | grub_printf ("Name\tRef Count\tDependencies\n"); | |
324 | grub_dl_iterate (print_module); | |
325 | ||
326 | return 0; | |
327 | } | |
328 | ||
329 | /* exit */ | |
330 | static grub_err_t | |
331 | grub_mini_cmd_exit (struct grub_command *cmd __attribute__ ((unused)), | |
332 | int argc __attribute__ ((unused)), | |
333 | char *argv[] __attribute__ ((unused))) | |
334 | { | |
335 | grub_exit (); | |
336 | return 0; | |
337 | } | |
338 | ||
cd4f42b0 RM |
339 | /* clear */ |
340 | static grub_err_t | |
341 | grub_mini_cmd_clear (struct grub_command *cmd __attribute__ ((unused)), | |
342 | int argc __attribute__ ((unused)), | |
343 | char *argv[] __attribute__ ((unused))) | |
344 | { | |
345 | grub_cls (); | |
346 | return 0; | |
347 | } | |
348 | ||
0d5d5653 | 349 | static grub_command_t cmd_cat, cmd_help, cmd_root; |
b1b797cb | 350 | static grub_command_t cmd_dump, cmd_rmmod, cmd_lsmod, cmd_exit; |
cd4f42b0 | 351 | static grub_command_t cmd_clear; |
b1b797cb | 352 | |
353 | GRUB_MOD_INIT(minicmd) | |
354 | { | |
b1b797cb | 355 | cmd_cat = |
356 | grub_register_command ("cat", grub_mini_cmd_cat, | |
77a79592 | 357 | N_("FILE"), N_("Show the contents of a file.")); |
b1b797cb | 358 | cmd_help = |
359 | grub_register_command ("help", grub_mini_cmd_help, | |
77a79592 | 360 | 0, N_("Show this message.")); |
b1b797cb | 361 | cmd_root = |
362 | grub_register_command ("root", grub_mini_cmd_root, | |
77a79592 | 363 | N_("[DEVICE]"), N_("Set the root device.")); |
b1b797cb | 364 | cmd_dump = |
365 | grub_register_command ("dump", grub_mini_cmd_dump, | |
77a79592 | 366 | N_("ADDR"), N_("Dump memory.")); |
b1b797cb | 367 | cmd_rmmod = |
368 | grub_register_command ("rmmod", grub_mini_cmd_rmmod, | |
77a79592 | 369 | N_("MODULE"), N_("Remove a module.")); |
b1b797cb | 370 | cmd_lsmod = |
371 | grub_register_command ("lsmod", grub_mini_cmd_lsmod, | |
77a79592 | 372 | 0, N_("Show loaded modules.")); |
b1b797cb | 373 | cmd_exit = |
374 | grub_register_command ("exit", grub_mini_cmd_exit, | |
77a79592 | 375 | 0, N_("Exit from GRUB.")); |
cd4f42b0 RM |
376 | cmd_clear = |
377 | grub_register_command ("clear", grub_mini_cmd_clear, | |
77a79592 | 378 | 0, N_("Clear the screen.")); |
b1b797cb | 379 | } |
380 | ||
381 | GRUB_MOD_FINI(minicmd) | |
382 | { | |
b1b797cb | 383 | grub_unregister_command (cmd_cat); |
384 | grub_unregister_command (cmd_help); | |
385 | grub_unregister_command (cmd_root); | |
386 | grub_unregister_command (cmd_dump); | |
387 | grub_unregister_command (cmd_rmmod); | |
388 | grub_unregister_command (cmd_lsmod); | |
389 | grub_unregister_command (cmd_exit); | |
cd4f42b0 | 390 | grub_unregister_command (cmd_clear); |
b1b797cb | 391 | } |