You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

image_cmd.c 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573
  1. /*
  2. * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as
  6. * published by the Free Software Foundation; either version 2 of the
  7. * License, or any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18. #include <stdint.h>
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <errno.h>
  22. #include <libgen.h>
  23. #include <getopt.h>
  24. #include <gpxe/image.h>
  25. #include <gpxe/command.h>
  26. #include <usr/imgmgmt.h>
  27. /** @file
  28. *
  29. * Image management commands
  30. *
  31. */
  32. enum image_action {
  33. IMG_FETCH = 0,
  34. IMG_LOAD,
  35. IMG_EXEC,
  36. };
  37. /**
  38. * Fill in image command line
  39. *
  40. * @v image Image
  41. * @v nargs Argument count
  42. * @v args Argument list
  43. * @ret rc Return status code
  44. */
  45. static int imgfill_cmdline ( struct image *image, unsigned int nargs,
  46. char **args ) {
  47. size_t len;
  48. unsigned int i;
  49. /* Determine total length of command line */
  50. len = 1; /* NUL */
  51. for ( i = 0 ; i < nargs ; i++ )
  52. len += ( 1 /* possible space */ + strlen ( args[i] ) );
  53. {
  54. char buf[len];
  55. char *ptr = buf;
  56. /* Assemble command line */
  57. buf[0] = '\0';
  58. for ( i = 0 ; i < nargs ; i++ ) {
  59. ptr += sprintf ( ptr, "%s%s", ( i ? " " : "" ),
  60. args[i] );
  61. }
  62. assert ( ptr < ( buf + len ) );
  63. return image_set_cmdline ( image, buf );
  64. }
  65. }
  66. /**
  67. * "imgfetch"/"module"/"kernel" command syntax message
  68. *
  69. * @v argv Argument list
  70. */
  71. static void imgfetch_core_syntax ( char **argv, enum image_action action ) {
  72. static const char *actions[] = {
  73. [IMG_FETCH] = "Fetch",
  74. [IMG_LOAD] = "Fetch and load",
  75. [IMG_EXEC] = "Fetch and execute",
  76. };
  77. printf ( "Usage:\n"
  78. " %s [-n|--name <name>] filename [arguments...]\n"
  79. "\n"
  80. "%s executable/loadable image\n",
  81. argv[0], actions[action] );
  82. }
  83. /**
  84. * The "imgfetch"/"module"/"kernel" command body
  85. *
  86. * @v image_type Image type to assign (or NULL)
  87. * @v load Image will be automatically loaded after fetching
  88. * @v argc Argument count
  89. * @v argv Argument list
  90. * @ret rc Return status code
  91. */
  92. static int imgfetch_core_exec ( struct image_type *image_type,
  93. enum image_action action,
  94. int argc, char **argv ) {
  95. static struct option longopts[] = {
  96. { "help", 0, NULL, 'h' },
  97. { "name", required_argument, NULL, 'n' },
  98. { NULL, 0, NULL, 0 },
  99. };
  100. struct image *image;
  101. const char *name = NULL;
  102. char *filename;
  103. int ( * image_register ) ( struct image *image );
  104. int c;
  105. int rc;
  106. /* Parse options */
  107. while ( ( c = getopt_long ( argc, argv, "hn:",
  108. longopts, NULL ) ) >= 0 ) {
  109. switch ( c ) {
  110. case 'n':
  111. /* Set image name */
  112. name = optarg;
  113. break;
  114. case 'h':
  115. /* Display help text */
  116. default:
  117. /* Unrecognised/invalid option */
  118. imgfetch_core_syntax ( argv, action );
  119. return -EINVAL;
  120. }
  121. }
  122. /* Need at least a filename remaining after the options */
  123. if ( optind == argc ) {
  124. imgfetch_core_syntax ( argv, action );
  125. return -EINVAL;
  126. }
  127. filename = argv[optind++];
  128. if ( ! name )
  129. name = basename ( filename );
  130. /* Allocate image */
  131. image = alloc_image();
  132. if ( ! image ) {
  133. printf ( "%s\n", strerror ( -ENOMEM ) );
  134. return -ENOMEM;
  135. }
  136. /* Fill in image name */
  137. if ( name ) {
  138. if ( ( rc = image_set_name ( image, name ) ) != 0 )
  139. return rc;
  140. }
  141. /* Set image type (if specified) */
  142. image->type = image_type;
  143. /* Fill in command line */
  144. if ( ( rc = imgfill_cmdline ( image, ( argc - optind ),
  145. &argv[optind] ) ) != 0 )
  146. return rc;
  147. /* Fetch the image */
  148. switch ( action ) {
  149. case IMG_FETCH:
  150. image_register = register_image;
  151. break;
  152. case IMG_LOAD:
  153. image_register = register_and_autoload_image;
  154. break;
  155. case IMG_EXEC:
  156. image_register = register_and_autoexec_image;
  157. break;
  158. default:
  159. assert ( 0 );
  160. return -EINVAL;
  161. }
  162. if ( ( rc = imgfetch ( image, filename, image_register ) ) != 0 ) {
  163. printf ( "Could not fetch %s: %s\n",
  164. filename, strerror ( rc ) );
  165. image_put ( image );
  166. return rc;
  167. }
  168. image_put ( image );
  169. return 0;
  170. }
  171. /**
  172. * The "imgfetch"/"module" command
  173. *
  174. * @v argc Argument count
  175. * @v argv Argument list
  176. * @ret rc Exit code
  177. */
  178. static int imgfetch_exec ( int argc, char **argv ) {
  179. int rc;
  180. if ( ( rc = imgfetch_core_exec ( NULL, IMG_FETCH,
  181. argc, argv ) ) != 0 )
  182. return rc;
  183. return 0;
  184. }
  185. /**
  186. * The "kernel" command
  187. *
  188. * @v argc Argument count
  189. * @v argv Argument list
  190. * @ret rc Exit code
  191. */
  192. static int kernel_exec ( int argc, char **argv ) {
  193. int rc;
  194. if ( ( rc = imgfetch_core_exec ( NULL, IMG_LOAD, argc, argv ) ) != 0 )
  195. return rc;
  196. return 0;
  197. }
  198. /**
  199. * "imgload" command syntax message
  200. *
  201. * @v argv Argument list
  202. */
  203. static void imgload_syntax ( char **argv ) {
  204. printf ( "Usage:\n"
  205. " %s <image name>\n"
  206. "\n"
  207. "Load executable/loadable image\n",
  208. argv[0] );
  209. }
  210. /**
  211. * The "imgload" command
  212. *
  213. * @v argc Argument count
  214. * @v argv Argument list
  215. * @ret rc Exit code
  216. */
  217. static int imgload_exec ( int argc, char **argv ) {
  218. static struct option longopts[] = {
  219. { "help", 0, NULL, 'h' },
  220. { NULL, 0, NULL, 0 },
  221. };
  222. struct image *image;
  223. const char *name;
  224. int c;
  225. int rc;
  226. /* Parse options */
  227. while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){
  228. switch ( c ) {
  229. case 'h':
  230. /* Display help text */
  231. default:
  232. /* Unrecognised/invalid option */
  233. imgload_syntax ( argv );
  234. return 1;
  235. }
  236. }
  237. /* Need exactly one image name remaining after the options */
  238. if ( optind != ( argc - 1 ) ) {
  239. imgload_syntax ( argv );
  240. return 1;
  241. }
  242. name = argv[optind];
  243. /* Load all specified images */
  244. image = find_image ( name );
  245. if ( ! image ) {
  246. printf ( "No such image: %s\n", name );
  247. return 1;
  248. }
  249. if ( ( rc = imgload ( image ) ) != 0 ) {
  250. printf ( "Could not load %s: %s\n", name, strerror ( rc ) );
  251. return rc;
  252. }
  253. return 0;
  254. }
  255. /**
  256. * "imgargs" command syntax message
  257. *
  258. * @v argv Argument list
  259. */
  260. static void imgargs_syntax ( char **argv ) {
  261. printf ( "Usage:\n"
  262. " %s <image name> [<arguments>...]\n"
  263. "\n"
  264. "Set arguments for executable/loadable image\n",
  265. argv[0] );
  266. }
  267. /**
  268. * The "imgargs" command body
  269. *
  270. * @v argc Argument count
  271. * @v argv Argument list
  272. * @ret rc Exit code
  273. */
  274. static int imgargs_exec ( int argc, char **argv ) {
  275. static struct option longopts[] = {
  276. { "help", 0, NULL, 'h' },
  277. { NULL, 0, NULL, 0 },
  278. };
  279. struct image *image;
  280. const char *name;
  281. int c;
  282. int rc;
  283. /* Parse options */
  284. while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){
  285. switch ( c ) {
  286. case 'h':
  287. /* Display help text */
  288. default:
  289. /* Unrecognised/invalid option */
  290. imgargs_syntax ( argv );
  291. return 1;
  292. }
  293. }
  294. /* Need at least an image name remaining after the options */
  295. if ( optind == argc ) {
  296. imgargs_syntax ( argv );
  297. return 1;
  298. }
  299. name = argv[optind++];
  300. /* Fill in command line */
  301. image = find_image ( name );
  302. if ( ! image ) {
  303. printf ( "No such image: %s\n", name );
  304. return 1;
  305. }
  306. if ( ( rc = imgfill_cmdline ( image, ( argc - optind ),
  307. &argv[optind] ) ) != 0 )
  308. return rc;
  309. return 0;
  310. }
  311. /**
  312. * "imgexec" command syntax message
  313. *
  314. * @v argv Argument list
  315. */
  316. static void imgexec_syntax ( char **argv ) {
  317. printf ( "Usage:\n"
  318. " %s <image name>\n"
  319. "\n"
  320. "Execute executable/loadable image\n",
  321. argv[0] );
  322. }
  323. /**
  324. * The "imgexec" command
  325. *
  326. * @v argc Argument count
  327. * @v argv Argument list
  328. * @ret rc Exit code
  329. */
  330. static int imgexec_exec ( int argc, char **argv ) {
  331. static struct option longopts[] = {
  332. { "help", 0, NULL, 'h' },
  333. { NULL, 0, NULL, 0 },
  334. };
  335. struct image *image;
  336. const char *name = NULL;
  337. int c;
  338. int rc;
  339. /* Parse options */
  340. while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){
  341. switch ( c ) {
  342. case 'h':
  343. /* Display help text */
  344. default:
  345. /* Unrecognised/invalid option */
  346. imgexec_syntax ( argv );
  347. return 1;
  348. }
  349. }
  350. /* Need no more than one image name */
  351. if ( optind != argc )
  352. name = argv[optind++];
  353. if ( optind != argc ) {
  354. imgexec_syntax ( argv );
  355. return 1;
  356. }
  357. /* Execute specified image */
  358. if ( name ) {
  359. image = find_image ( name );
  360. if ( ! image ) {
  361. printf ( "No such image: %s\n", name );
  362. return 1;
  363. }
  364. } else {
  365. image = imgautoselect();
  366. if ( ! image ) {
  367. printf ( "No (unique) loaded image\n" );
  368. return 1;
  369. }
  370. }
  371. if ( ( rc = imgexec ( image ) ) != 0 ) {
  372. printf ( "Could not execute %s: %s\n",
  373. image->name, strerror ( rc ) );
  374. return 1;
  375. }
  376. return 0;
  377. }
  378. /**
  379. * "imgstat" command syntax message
  380. *
  381. * @v argv Argument list
  382. */
  383. static void imgstat_syntax ( char **argv ) {
  384. printf ( "Usage:\n"
  385. " %s\n"
  386. "\n"
  387. "List executable/loadable images\n",
  388. argv[0] );
  389. }
  390. /**
  391. * The "imgstat" command
  392. *
  393. * @v argc Argument count
  394. * @v argv Argument list
  395. * @ret rc Exit code
  396. */
  397. static int imgstat_exec ( int argc, char **argv ) {
  398. static struct option longopts[] = {
  399. { "help", 0, NULL, 'h' },
  400. { NULL, 0, NULL, 0 },
  401. };
  402. struct image *image;
  403. int c;
  404. /* Parse options */
  405. while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){
  406. switch ( c ) {
  407. case 'h':
  408. /* Display help text */
  409. default:
  410. /* Unrecognised/invalid option */
  411. imgstat_syntax ( argv );
  412. return 1;
  413. }
  414. }
  415. /* No arguments */
  416. if ( optind != argc ) {
  417. imgstat_syntax ( argv );
  418. return 1;
  419. }
  420. /* Show status of all images */
  421. for_each_image ( image ) {
  422. imgstat ( image );
  423. }
  424. return 0;
  425. }
  426. /**
  427. * "imgstat" command syntax message
  428. *
  429. * @v argv Argument list
  430. */
  431. static void imgfree_syntax ( char **argv ) {
  432. printf ( "Usage:\n"
  433. " %s\n"
  434. "\n"
  435. "Free all executable/loadable images\n",
  436. argv[0] );
  437. }
  438. /**
  439. * The "imgfree" command
  440. *
  441. * @v argc Argument count
  442. * @v argv Argument list
  443. * @ret rc Exit code
  444. */
  445. static int imgfree_exec ( int argc, char **argv ) {
  446. static struct option longopts[] = {
  447. { "help", 0, NULL, 'h' },
  448. { NULL, 0, NULL, 0 },
  449. };
  450. struct image *image;
  451. struct image *tmp;
  452. int c;
  453. /* Parse options */
  454. while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){
  455. switch ( c ) {
  456. case 'h':
  457. /* Display help text */
  458. default:
  459. /* Unrecognised/invalid option */
  460. imgfree_syntax ( argv );
  461. return 1;
  462. }
  463. }
  464. /* No arguments */
  465. if ( optind != argc ) {
  466. imgfree_syntax ( argv );
  467. return 1;
  468. }
  469. /* Free all images */
  470. list_for_each_entry_safe ( image, tmp, &images, list ) {
  471. imgfree ( image );
  472. }
  473. return 0;
  474. }
  475. /** Image management commands */
  476. struct command image_commands[] __command = {
  477. {
  478. .name = "imgfetch",
  479. .exec = imgfetch_exec,
  480. },
  481. {
  482. .name = "module",
  483. .exec = imgfetch_exec, /* synonym for "imgfetch" */
  484. },
  485. {
  486. .name = "initrd",
  487. .exec = imgfetch_exec, /* synonym for "imgfetch" */
  488. },
  489. {
  490. .name = "kernel",
  491. .exec = kernel_exec,
  492. },
  493. {
  494. .name = "imgload",
  495. .exec = imgload_exec,
  496. },
  497. {
  498. .name = "imgargs",
  499. .exec = imgargs_exec,
  500. },
  501. {
  502. .name = "imgexec",
  503. .exec = imgexec_exec,
  504. },
  505. {
  506. .name = "boot", /* synonym for "imgexec" */
  507. .exec = imgexec_exec,
  508. },
  509. {
  510. .name = "imgstat",
  511. .exec = imgstat_exec,
  512. },
  513. {
  514. .name = "imgfree",
  515. .exec = imgfree_exec,
  516. },
  517. };