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.

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