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.c 7.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. /*
  2. * Copyright (C) 2006 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 <stddef.h>
  19. #include <string.h>
  20. #include <stdlib.h>
  21. #include <stdio.h>
  22. #include <errno.h>
  23. #include <assert.h>
  24. #include <libgen.h>
  25. #include <gpxe/list.h>
  26. #include <gpxe/umalloc.h>
  27. #include <gpxe/uri.h>
  28. #include <gpxe/image.h>
  29. /** @file
  30. *
  31. * Executable/loadable images
  32. *
  33. */
  34. /** List of registered images */
  35. struct list_head images = LIST_HEAD_INIT ( images );
  36. /**
  37. * Free executable/loadable image
  38. *
  39. * @v refcnt Reference counter
  40. */
  41. static void free_image ( struct refcnt *refcnt ) {
  42. struct image *image = container_of ( refcnt, struct image, refcnt );
  43. uri_put ( image->uri );
  44. ufree ( image->data );
  45. image_put ( image->replacement );
  46. free ( image );
  47. DBGC ( image, "IMAGE %p freed\n", image );
  48. }
  49. /**
  50. * Allocate executable/loadable image
  51. *
  52. * @ret image Executable/loadable image
  53. */
  54. struct image * alloc_image ( void ) {
  55. struct image *image;
  56. image = zalloc ( sizeof ( *image ) );
  57. if ( image ) {
  58. image->refcnt.free = free_image;
  59. }
  60. return image;
  61. }
  62. /**
  63. * Set image URI
  64. *
  65. * @v image Image
  66. * @v URI New image URI
  67. * @ret rc Return status code
  68. *
  69. * If no name is set, the name will be updated to the base name of the
  70. * URI path (if any).
  71. */
  72. int image_set_uri ( struct image *image, struct uri *uri ) {
  73. const char *path = uri->path;
  74. /* Replace URI reference */
  75. uri_put ( image->uri );
  76. image->uri = uri_get ( uri );
  77. /* Set name if none already specified */
  78. if ( path && ( ! image->name[0] ) )
  79. image_set_name ( image, basename ( ( char * ) path ) );
  80. return 0;
  81. }
  82. /**
  83. * Set image command line
  84. *
  85. * @v image Image
  86. * @v cmdline New image command line
  87. * @ret rc Return status code
  88. */
  89. int image_set_cmdline ( struct image *image, const char *cmdline ) {
  90. free ( image->cmdline );
  91. image->cmdline = strdup ( cmdline );
  92. if ( ! image->cmdline )
  93. return -ENOMEM;
  94. return 0;
  95. }
  96. /**
  97. * Register executable/loadable image
  98. *
  99. * @v image Executable/loadable image
  100. * @ret rc Return status code
  101. */
  102. int register_image ( struct image *image ) {
  103. static unsigned int imgindex = 0;
  104. /* Create image name if it doesn't already have one */
  105. if ( ! image->name[0] ) {
  106. snprintf ( image->name, sizeof ( image->name ), "img%d",
  107. imgindex++ );
  108. }
  109. /* Add to image list */
  110. image_get ( image );
  111. list_add_tail ( &image->list, &images );
  112. DBGC ( image, "IMAGE %p at [%lx,%lx) registered as %s\n",
  113. image, user_to_phys ( image->data, 0 ),
  114. user_to_phys ( image->data, image->len ), image->name );
  115. return 0;
  116. }
  117. /**
  118. * Unregister executable/loadable image
  119. *
  120. * @v image Executable/loadable image
  121. */
  122. void unregister_image ( struct image *image ) {
  123. DBGC ( image, "IMAGE %p unregistered\n", image );
  124. list_del ( &image->list );
  125. image_put ( image );
  126. }
  127. /**
  128. * Find image by name
  129. *
  130. * @v name Image name
  131. * @ret image Executable/loadable image, or NULL
  132. */
  133. struct image * find_image ( const char *name ) {
  134. struct image *image;
  135. list_for_each_entry ( image, &images, list ) {
  136. if ( strcmp ( image->name, name ) == 0 )
  137. return image;
  138. }
  139. return NULL;
  140. }
  141. /**
  142. * Load executable/loadable image into memory
  143. *
  144. * @v image Executable/loadable image
  145. * @v type Executable/loadable image type
  146. * @ret rc Return status code
  147. */
  148. static int image_load_type ( struct image *image, struct image_type *type ) {
  149. int rc;
  150. /* Check image is actually loadable */
  151. if ( ! type->load )
  152. return -ENOEXEC;
  153. /* Try the image loader */
  154. if ( ( rc = type->load ( image ) ) != 0 ) {
  155. DBGC ( image, "IMAGE %p could not load as %s: %s\n",
  156. image, type->name, strerror ( rc ) );
  157. return rc;
  158. }
  159. /* Flag as loaded */
  160. image->flags |= IMAGE_LOADED;
  161. return 0;
  162. }
  163. /**
  164. * Load executable/loadable image into memory
  165. *
  166. * @v image Executable/loadable image
  167. * @ret rc Return status code
  168. */
  169. int image_load ( struct image *image ) {
  170. assert ( image->type != NULL );
  171. return image_load_type ( image, image->type );
  172. }
  173. /**
  174. * Autodetect image type and load executable/loadable image into memory
  175. *
  176. * @v image Executable/loadable image
  177. * @ret rc Return status code
  178. */
  179. int image_autoload ( struct image *image ) {
  180. struct image_type *type;
  181. int rc;
  182. /* If image already has a type, use it */
  183. if ( image->type )
  184. return image_load ( image );
  185. /* Otherwise probe for a suitable type */
  186. for_each_table_entry ( type, IMAGE_TYPES ) {
  187. DBGC ( image, "IMAGE %p trying type %s\n", image, type->name );
  188. rc = image_load_type ( image, type );
  189. if ( image->type == NULL )
  190. continue;
  191. return rc;
  192. }
  193. DBGC ( image, "IMAGE %p format not recognised\n", image );
  194. return -ENOEXEC;
  195. }
  196. /**
  197. * Execute loaded image
  198. *
  199. * @v image Loaded image
  200. * @ret rc Return status code
  201. */
  202. int image_exec ( struct image *image ) {
  203. struct image *replacement;
  204. struct uri *old_cwuri;
  205. int rc;
  206. /* Image must be loaded first */
  207. if ( ! ( image->flags & IMAGE_LOADED ) ) {
  208. DBGC ( image, "IMAGE %p could not execute: not loaded\n",
  209. image );
  210. return -ENOTTY;
  211. }
  212. assert ( image->type != NULL );
  213. /* Check that image is actually executable */
  214. if ( ! image->type->exec )
  215. return -ENOEXEC;
  216. /* Switch current working directory to be that of the image itself */
  217. old_cwuri = uri_get ( cwuri );
  218. churi ( image->uri );
  219. /* Take out a temporary reference to the image. This allows
  220. * the image to unregister itself if necessary, without
  221. * automatically freeing itself.
  222. */
  223. image_get ( image );
  224. /* Try executing the image */
  225. if ( ( rc = image->type->exec ( image ) ) != 0 ) {
  226. DBGC ( image, "IMAGE %p could not execute: %s\n",
  227. image, strerror ( rc ) );
  228. /* Do not return yet; we still have clean-up to do */
  229. }
  230. /* Pick up replacement image before we drop the original
  231. * image's temporary reference.
  232. */
  233. replacement = image->replacement;
  234. /* Drop temporary reference to the original image */
  235. image_put ( image );
  236. /* Reset current working directory */
  237. churi ( old_cwuri );
  238. uri_put ( old_cwuri );
  239. /* Tail-recurse into replacement image, if one exists */
  240. if ( replacement ) {
  241. DBGC ( image, "IMAGE %p replacing self with IMAGE %p\n",
  242. image, replacement );
  243. if ( ( rc = image_exec ( replacement ) ) != 0 )
  244. return rc;
  245. }
  246. return rc;
  247. }
  248. /**
  249. * Register and autoload an image
  250. *
  251. * @v image Image
  252. * @ret rc Return status code
  253. */
  254. int register_and_autoload_image ( struct image *image ) {
  255. int rc;
  256. if ( ( rc = register_image ( image ) ) != 0 )
  257. return rc;
  258. if ( ( rc = image_autoload ( image ) ) != 0 )
  259. return rc;
  260. return 0;
  261. }
  262. /**
  263. * Register and autoexec an image
  264. *
  265. * @v image Image
  266. * @ret rc Return status code
  267. */
  268. int register_and_autoexec_image ( struct image *image ) {
  269. int rc;
  270. if ( ( rc = register_and_autoload_image ( image ) ) != 0 )
  271. return rc;
  272. if ( ( rc = image_exec ( image ) ) != 0 )
  273. return rc;
  274. return 0;
  275. }