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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593
  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. * The "chain" command
  200. *
  201. * @v argc Argument count
  202. * @v argv Argument list
  203. * @ret rc Exit code
  204. */
  205. static int chain_exec ( int argc, char **argv) {
  206. int rc;
  207. if ( ( rc = imgfetch_core_exec ( NULL, IMG_EXEC, argc, argv ) ) != 0 )
  208. return rc;
  209. return 0;
  210. }
  211. /**
  212. * "imgload" command syntax message
  213. *
  214. * @v argv Argument list
  215. */
  216. static void imgload_syntax ( char **argv ) {
  217. printf ( "Usage:\n"
  218. " %s <image name>\n"
  219. "\n"
  220. "Load executable/loadable image\n",
  221. argv[0] );
  222. }
  223. /**
  224. * The "imgload" command
  225. *
  226. * @v argc Argument count
  227. * @v argv Argument list
  228. * @ret rc Exit code
  229. */
  230. static int imgload_exec ( int argc, char **argv ) {
  231. static struct option longopts[] = {
  232. { "help", 0, NULL, 'h' },
  233. { NULL, 0, NULL, 0 },
  234. };
  235. struct image *image;
  236. const char *name;
  237. int c;
  238. int rc;
  239. /* Parse options */
  240. while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){
  241. switch ( c ) {
  242. case 'h':
  243. /* Display help text */
  244. default:
  245. /* Unrecognised/invalid option */
  246. imgload_syntax ( argv );
  247. return 1;
  248. }
  249. }
  250. /* Need exactly one image name remaining after the options */
  251. if ( optind != ( argc - 1 ) ) {
  252. imgload_syntax ( argv );
  253. return 1;
  254. }
  255. name = argv[optind];
  256. /* Load all specified images */
  257. image = find_image ( name );
  258. if ( ! image ) {
  259. printf ( "No such image: %s\n", name );
  260. return 1;
  261. }
  262. if ( ( rc = imgload ( image ) ) != 0 ) {
  263. printf ( "Could not load %s: %s\n", name, strerror ( rc ) );
  264. return rc;
  265. }
  266. return 0;
  267. }
  268. /**
  269. * "imgargs" command syntax message
  270. *
  271. * @v argv Argument list
  272. */
  273. static void imgargs_syntax ( char **argv ) {
  274. printf ( "Usage:\n"
  275. " %s <image name> [<arguments>...]\n"
  276. "\n"
  277. "Set arguments for executable/loadable image\n",
  278. argv[0] );
  279. }
  280. /**
  281. * The "imgargs" command body
  282. *
  283. * @v argc Argument count
  284. * @v argv Argument list
  285. * @ret rc Exit code
  286. */
  287. static int imgargs_exec ( int argc, char **argv ) {
  288. static struct option longopts[] = {
  289. { "help", 0, NULL, 'h' },
  290. { NULL, 0, NULL, 0 },
  291. };
  292. struct image *image;
  293. const char *name;
  294. int c;
  295. int rc;
  296. /* Parse options */
  297. while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){
  298. switch ( c ) {
  299. case 'h':
  300. /* Display help text */
  301. default:
  302. /* Unrecognised/invalid option */
  303. imgargs_syntax ( argv );
  304. return 1;
  305. }
  306. }
  307. /* Need at least an image name remaining after the options */
  308. if ( optind == argc ) {
  309. imgargs_syntax ( argv );
  310. return 1;
  311. }
  312. name = argv[optind++];
  313. /* Fill in command line */
  314. image = find_image ( name );
  315. if ( ! image ) {
  316. printf ( "No such image: %s\n", name );
  317. return 1;
  318. }
  319. if ( ( rc = imgfill_cmdline ( image, ( argc - optind ),
  320. &argv[optind] ) ) != 0 )
  321. return rc;
  322. return 0;
  323. }
  324. /**
  325. * "imgexec" command syntax message
  326. *
  327. * @v argv Argument list
  328. */
  329. static void imgexec_syntax ( char **argv ) {
  330. printf ( "Usage:\n"
  331. " %s <image name>\n"
  332. "\n"
  333. "Execute executable/loadable image\n",
  334. argv[0] );
  335. }
  336. /**
  337. * The "imgexec" command
  338. *
  339. * @v argc Argument count
  340. * @v argv Argument list
  341. * @ret rc Exit code
  342. */
  343. static int imgexec_exec ( int argc, char **argv ) {
  344. static struct option longopts[] = {
  345. { "help", 0, NULL, 'h' },
  346. { NULL, 0, NULL, 0 },
  347. };
  348. struct image *image;
  349. const char *name = NULL;
  350. int c;
  351. int rc;
  352. /* Parse options */
  353. while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){
  354. switch ( c ) {
  355. case 'h':
  356. /* Display help text */
  357. default:
  358. /* Unrecognised/invalid option */
  359. imgexec_syntax ( argv );
  360. return 1;
  361. }
  362. }
  363. /* Need no more than one image name */
  364. if ( optind != argc )
  365. name = argv[optind++];
  366. if ( optind != argc ) {
  367. imgexec_syntax ( argv );
  368. return 1;
  369. }
  370. /* Execute specified image */
  371. if ( name ) {
  372. image = find_image ( name );
  373. if ( ! image ) {
  374. printf ( "No such image: %s\n", name );
  375. return 1;
  376. }
  377. } else {
  378. image = imgautoselect();
  379. if ( ! image ) {
  380. printf ( "No (unique) loaded image\n" );
  381. return 1;
  382. }
  383. }
  384. if ( ( rc = imgexec ( image ) ) != 0 ) {
  385. printf ( "Could not execute %s: %s\n",
  386. image->name, strerror ( rc ) );
  387. return 1;
  388. }
  389. return 0;
  390. }
  391. /**
  392. * "imgstat" command syntax message
  393. *
  394. * @v argv Argument list
  395. */
  396. static void imgstat_syntax ( char **argv ) {
  397. printf ( "Usage:\n"
  398. " %s\n"
  399. "\n"
  400. "List executable/loadable images\n",
  401. argv[0] );
  402. }
  403. /**
  404. * The "imgstat" command
  405. *
  406. * @v argc Argument count
  407. * @v argv Argument list
  408. * @ret rc Exit code
  409. */
  410. static int imgstat_exec ( int argc, char **argv ) {
  411. static struct option longopts[] = {
  412. { "help", 0, NULL, 'h' },
  413. { NULL, 0, NULL, 0 },
  414. };
  415. struct image *image;
  416. int c;
  417. /* Parse options */
  418. while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){
  419. switch ( c ) {
  420. case 'h':
  421. /* Display help text */
  422. default:
  423. /* Unrecognised/invalid option */
  424. imgstat_syntax ( argv );
  425. return 1;
  426. }
  427. }
  428. /* No arguments */
  429. if ( optind != argc ) {
  430. imgstat_syntax ( argv );
  431. return 1;
  432. }
  433. /* Show status of all images */
  434. for_each_image ( image ) {
  435. imgstat ( image );
  436. }
  437. return 0;
  438. }
  439. /**
  440. * "imgstat" command syntax message
  441. *
  442. * @v argv Argument list
  443. */
  444. static void imgfree_syntax ( char **argv ) {
  445. printf ( "Usage:\n"
  446. " %s\n"
  447. "\n"
  448. "Free all executable/loadable images\n",
  449. argv[0] );
  450. }
  451. /**
  452. * The "imgfree" command
  453. *
  454. * @v argc Argument count
  455. * @v argv Argument list
  456. * @ret rc Exit code
  457. */
  458. static int imgfree_exec ( int argc, char **argv ) {
  459. static struct option longopts[] = {
  460. { "help", 0, NULL, 'h' },
  461. { NULL, 0, NULL, 0 },
  462. };
  463. struct image *image;
  464. struct image *tmp;
  465. int c;
  466. /* Parse options */
  467. while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){
  468. switch ( c ) {
  469. case 'h':
  470. /* Display help text */
  471. default:
  472. /* Unrecognised/invalid option */
  473. imgfree_syntax ( argv );
  474. return 1;
  475. }
  476. }
  477. /* No arguments */
  478. if ( optind != argc ) {
  479. imgfree_syntax ( argv );
  480. return 1;
  481. }
  482. /* Free all images */
  483. list_for_each_entry_safe ( image, tmp, &images, list ) {
  484. imgfree ( image );
  485. }
  486. return 0;
  487. }
  488. /** Image management commands */
  489. struct command image_commands[] __command = {
  490. {
  491. .name = "imgfetch",
  492. .exec = imgfetch_exec,
  493. },
  494. {
  495. .name = "module",
  496. .exec = imgfetch_exec, /* synonym for "imgfetch" */
  497. },
  498. {
  499. .name = "initrd",
  500. .exec = imgfetch_exec, /* synonym for "imgfetch" */
  501. },
  502. {
  503. .name = "kernel",
  504. .exec = kernel_exec,
  505. },
  506. {
  507. .name = "chain",
  508. .exec = chain_exec,
  509. },
  510. {
  511. .name = "imgload",
  512. .exec = imgload_exec,
  513. },
  514. {
  515. .name = "imgargs",
  516. .exec = imgargs_exec,
  517. },
  518. {
  519. .name = "imgexec",
  520. .exec = imgexec_exec,
  521. },
  522. {
  523. .name = "boot", /* synonym for "imgexec" */
  524. .exec = imgexec_exec,
  525. },
  526. {
  527. .name = "imgstat",
  528. .exec = imgstat_exec,
  529. },
  530. {
  531. .name = "imgfree",
  532. .exec = imgfree_exec,
  533. },
  534. };