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 9.9KB

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