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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  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., 51 Franklin Street, Fifth Floor, Boston, MA
  17. * 02110-1301, USA.
  18. *
  19. * You can also choose to distribute this program under the terms of
  20. * the Unmodified Binary Distribution Licence (as given in the file
  21. * COPYING.UBDL), provided that you have satisfied its requirements.
  22. */
  23. FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  24. #include <stdint.h>
  25. #include <stdlib.h>
  26. #include <stdio.h>
  27. #include <errno.h>
  28. #include <getopt.h>
  29. #include <ipxe/image.h>
  30. #include <ipxe/command.h>
  31. #include <ipxe/parseopt.h>
  32. #include <ipxe/shell.h>
  33. #include <usr/imgmgmt.h>
  34. /** @file
  35. *
  36. * Image management commands
  37. *
  38. */
  39. /** "img{single}" options */
  40. struct imgsingle_options {
  41. /** Image name */
  42. char *name;
  43. /** Download timeout */
  44. unsigned long timeout;
  45. /** Replace image */
  46. int replace;
  47. /** Free image after execution */
  48. int autofree;
  49. };
  50. /** "img{single}" option list */
  51. static union {
  52. /* "imgexec" takes all three options */
  53. struct option_descriptor imgexec[4];
  54. /* Other "img{single}" commands take only --name, --timeout,
  55. * and --autofree
  56. */
  57. struct option_descriptor imgsingle[3];
  58. } opts = {
  59. .imgexec = {
  60. OPTION_DESC ( "name", 'n', required_argument,
  61. struct imgsingle_options, name, parse_string ),
  62. OPTION_DESC ( "timeout", 't', required_argument,
  63. struct imgsingle_options, timeout, parse_timeout),
  64. OPTION_DESC ( "autofree", 'a', no_argument,
  65. struct imgsingle_options, autofree, parse_flag ),
  66. OPTION_DESC ( "replace", 'r', no_argument,
  67. struct imgsingle_options, replace, parse_flag ),
  68. },
  69. };
  70. /** An "img{single}" family command descriptor */
  71. struct imgsingle_descriptor {
  72. /** Command descriptor */
  73. struct command_descriptor *cmd;
  74. /** Function to use to acquire the image */
  75. int ( * acquire ) ( const char *name, unsigned long timeout,
  76. struct image **image );
  77. /** Pre-action to take upon image, or NULL */
  78. void ( * preaction ) ( struct image *image );
  79. /** Action to take upon image, or NULL */
  80. int ( * action ) ( struct image *image,
  81. struct imgsingle_options *opts );
  82. /** Verb to describe action */
  83. const char *verb;
  84. };
  85. /**
  86. * The "img{single}" family of commands
  87. *
  88. * @v argc Argument count
  89. * @v argv Argument list
  90. * @v desc "img{single}" command descriptor
  91. * @v action_name Action name (for error messages)
  92. * @v action Action to take upon image
  93. * @ret rc Return status code
  94. */
  95. static int imgsingle_exec ( int argc, char **argv,
  96. struct imgsingle_descriptor *desc ) {
  97. struct imgsingle_options opts;
  98. char *name_uri = NULL;
  99. char *cmdline = NULL;
  100. struct image *image;
  101. int rc;
  102. /* Parse options */
  103. if ( ( rc = parse_options ( argc, argv, desc->cmd, &opts ) ) != 0 )
  104. goto err_parse_options;
  105. /* Parse name/URI string and command line, if present */
  106. if ( optind < argc ) {
  107. name_uri = argv[optind];
  108. if ( argv[ optind + 1 ] != NULL ) {
  109. cmdline = concat_args ( &argv[ optind + 1 ] );
  110. if ( ! cmdline ) {
  111. rc = -ENOMEM;
  112. goto err_parse_cmdline;
  113. }
  114. }
  115. }
  116. /* Acquire the image */
  117. if ( name_uri ) {
  118. if ( ( rc = desc->acquire ( name_uri, opts.timeout,
  119. &image ) ) != 0 )
  120. goto err_acquire;
  121. } else {
  122. image = image_find_selected();
  123. if ( ! image ) {
  124. printf ( "No image selected\n" );
  125. goto err_acquire;
  126. }
  127. }
  128. /* Carry out command pre-action, if applicable */
  129. if ( desc->preaction )
  130. desc->preaction ( image );
  131. /* Set the image name, if applicable */
  132. if ( opts.name ) {
  133. if ( ( rc = image_set_name ( image, opts.name ) ) != 0 ) {
  134. printf ( "Could not name image: %s\n",
  135. strerror ( rc ) );
  136. goto err_set_name;
  137. }
  138. }
  139. /* Set the command-line arguments, if applicable */
  140. if ( cmdline ) {
  141. if ( ( rc = image_set_cmdline ( image, cmdline ) ) != 0 ) {
  142. printf ( "Could not set arguments: %s\n",
  143. strerror ( rc ) );
  144. goto err_set_cmdline;
  145. }
  146. }
  147. /* Set the auto-unregister flag, if applicable */
  148. if ( opts.autofree )
  149. image->flags |= IMAGE_AUTO_UNREGISTER;
  150. /* Carry out command action, if applicable */
  151. if ( desc->action ) {
  152. if ( ( rc = desc->action ( image, &opts ) ) != 0 ) {
  153. printf ( "Could not %s: %s\n",
  154. desc->verb, strerror ( rc ) );
  155. goto err_action;
  156. }
  157. }
  158. /* Success */
  159. rc = 0;
  160. err_action:
  161. err_set_cmdline:
  162. err_set_name:
  163. err_acquire:
  164. free ( cmdline );
  165. err_parse_cmdline:
  166. err_parse_options:
  167. return rc;
  168. }
  169. /** "imgfetch" command descriptor */
  170. static struct command_descriptor imgfetch_cmd =
  171. COMMAND_DESC ( struct imgsingle_options, opts.imgsingle,
  172. 1, MAX_ARGUMENTS, "<uri> [<arguments>...]" );
  173. /** "imgfetch" family command descriptor */
  174. struct imgsingle_descriptor imgfetch_desc = {
  175. .cmd = &imgfetch_cmd,
  176. .acquire = imgdownload_string,
  177. };
  178. /**
  179. * The "imgfetch" command
  180. *
  181. * @v argc Argument count
  182. * @v argv Argument list
  183. * @ret rc Return status code
  184. */
  185. static int imgfetch_exec ( int argc, char **argv ) {
  186. return imgsingle_exec ( argc, argv, &imgfetch_desc );
  187. }
  188. /**
  189. * "imgselect" command action
  190. *
  191. * @v image Image
  192. * @v opts Options
  193. * @ret rc Return status code
  194. */
  195. static int imgselect ( struct image *image,
  196. struct imgsingle_options *opts __unused ) {
  197. return image_select ( image );
  198. }
  199. /** "imgselect" command descriptor */
  200. static struct command_descriptor imgselect_cmd =
  201. COMMAND_DESC ( struct imgsingle_options, opts.imgsingle,
  202. 1, MAX_ARGUMENTS, "<uri|image> [<arguments>...]" );
  203. /** "imgselect" family command descriptor */
  204. struct imgsingle_descriptor imgselect_desc = {
  205. .cmd = &imgselect_cmd,
  206. .acquire = imgacquire,
  207. .action = imgselect,
  208. .verb = "select",
  209. };
  210. /**
  211. * The "imgselect" command
  212. *
  213. * @v argc Argument count
  214. * @v argv Argument list
  215. * @ret rc Return status code
  216. */
  217. static int imgselect_exec ( int argc, char **argv ) {
  218. return imgsingle_exec ( argc, argv, &imgselect_desc );
  219. }
  220. /** "imgexec" command descriptor */
  221. static struct command_descriptor imgexec_cmd =
  222. COMMAND_DESC ( struct imgsingle_options, opts.imgexec,
  223. 0, MAX_ARGUMENTS, "[<uri|image> [<arguments>...]]" );
  224. /**
  225. * "imgexec" command action
  226. *
  227. * @v image Image
  228. * @v opts Options
  229. * @ret rc Return status code
  230. */
  231. static int imgexec ( struct image *image, struct imgsingle_options *opts ) {
  232. int rc;
  233. /* Perform replacement or execution as applicable */
  234. if ( opts->replace ) {
  235. /* Try to replace image */
  236. if ( ( rc = image_replace ( image ) ) != 0 )
  237. return rc;
  238. /* Stop script and tail-recurse into replacement image */
  239. shell_stop ( SHELL_STOP_COMMAND_SEQUENCE );
  240. } else {
  241. /* Try to execute image */
  242. if ( ( rc = image_exec ( image ) ) != 0 )
  243. return rc;
  244. }
  245. return 0;
  246. }
  247. /** "imgexec" family command descriptor */
  248. struct imgsingle_descriptor imgexec_desc = {
  249. .cmd = &imgexec_cmd,
  250. .acquire = imgacquire,
  251. .action = imgexec,
  252. .verb = "boot",
  253. };
  254. /**
  255. * The "imgexec" command
  256. *
  257. * @v argc Argument count
  258. * @v argv Argument list
  259. * @ret rc Return status code
  260. */
  261. static int imgexec_exec ( int argc, char **argv) {
  262. return imgsingle_exec ( argc, argv, &imgexec_desc );
  263. }
  264. /** "imgargs" command descriptor */
  265. static struct command_descriptor imgargs_cmd =
  266. COMMAND_DESC ( struct imgsingle_options, opts.imgsingle,
  267. 1, MAX_ARGUMENTS, "<uri|image> [<arguments>...]" );
  268. /** "imgargs" family command descriptor */
  269. struct imgsingle_descriptor imgargs_desc = {
  270. .cmd = &imgargs_cmd,
  271. .acquire = imgacquire,
  272. .preaction = image_clear_cmdline,
  273. };
  274. /**
  275. * The "imgargs" command body
  276. *
  277. * @v argc Argument count
  278. * @v argv Argument list
  279. * @ret rc Return status code
  280. */
  281. static int imgargs_exec ( int argc, char **argv ) {
  282. return imgsingle_exec ( argc, argv, &imgargs_desc );
  283. }
  284. /** "img{multi}" options */
  285. struct imgmulti_options {};
  286. /** "img{multi}" option list */
  287. static struct option_descriptor imgmulti_opts[] = {};
  288. /** "img{multi}" command descriptor */
  289. static struct command_descriptor imgmulti_cmd =
  290. COMMAND_DESC ( struct imgmulti_options, imgmulti_opts, 0, MAX_ARGUMENTS,
  291. "[<image>...]" );
  292. /**
  293. * The "img{multi}" family of commands
  294. *
  295. * @v argc Argument count
  296. * @v argv Argument list
  297. * @v payload Function to execute on each image
  298. * @ret rc Return status code
  299. */
  300. static int imgmulti_exec ( int argc, char **argv,
  301. void ( * payload ) ( struct image *image ) ) {
  302. struct imgmulti_options opts;
  303. struct image *image;
  304. struct image *tmp;
  305. int i;
  306. int rc;
  307. /* Parse options */
  308. if ( ( rc = parse_options ( argc, argv, &imgmulti_cmd, &opts ) ) != 0 )
  309. return rc;
  310. /* If no images are explicitly specified, process all images */
  311. if ( optind == argc ) {
  312. for_each_image_safe ( image, tmp )
  313. payload ( image );
  314. return 0;
  315. }
  316. /* Otherwise, process specified images */
  317. for ( i = optind ; i < argc ; i++ ) {
  318. image = find_image ( argv[i] );
  319. if ( ! image ) {
  320. printf ( "\"%s\": no such image\n", argv[i] );
  321. return -ENOENT;
  322. }
  323. payload ( image );
  324. }
  325. return 0;
  326. }
  327. /**
  328. * The "imgstat" command
  329. *
  330. * @v argc Argument count
  331. * @v argv Argument list
  332. * @ret rc Return status code
  333. */
  334. static int imgstat_exec ( int argc, char **argv ) {
  335. return imgmulti_exec ( argc, argv, imgstat );
  336. }
  337. /**
  338. * The "imgfree" command
  339. *
  340. * @v argc Argument count
  341. * @v argv Argument list
  342. * @ret rc Return status code
  343. */
  344. static int imgfree_exec ( int argc, char **argv ) {
  345. return imgmulti_exec ( argc, argv, unregister_image );
  346. }
  347. /** Image management commands */
  348. struct command image_commands[] __command = {
  349. {
  350. .name = "imgfetch",
  351. .exec = imgfetch_exec,
  352. },
  353. {
  354. .name = "module",
  355. .exec = imgfetch_exec, /* synonym for "imgfetch" */
  356. },
  357. {
  358. .name = "initrd",
  359. .exec = imgfetch_exec, /* synonym for "imgfetch" */
  360. },
  361. {
  362. .name = "kernel",
  363. .exec = imgselect_exec, /* synonym for "imgselect" */
  364. },
  365. {
  366. .name = "chain",
  367. .exec = imgexec_exec, /* synonym for "imgexec" */
  368. },
  369. {
  370. .name = "imgselect",
  371. .exec = imgselect_exec,
  372. },
  373. {
  374. .name = "imgload",
  375. .exec = imgselect_exec, /* synonym for "imgselect" */
  376. },
  377. {
  378. .name = "imgargs",
  379. .exec = imgargs_exec,
  380. },
  381. {
  382. .name = "imgexec",
  383. .exec = imgexec_exec,
  384. },
  385. {
  386. .name = "boot", /* synonym for "imgexec" */
  387. .exec = imgexec_exec,
  388. },
  389. {
  390. .name = "imgstat",
  391. .exec = imgstat_exec,
  392. },
  393. {
  394. .name = "imgfree",
  395. .exec = imgfree_exec,
  396. },
  397. };