bsdXX.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680
  1. #include <grub/loader.h>
  2. #include <grub/i386/bsd.h>
  3. #include <grub/mm.h>
  4. #include <grub/elf.h>
  5. #include <grub/misc.h>
  6. #include <grub/i386/relocator.h>
  7. #include <grub/i18n.h>
  8. #define ALIGN_PAGE(a) ALIGN_UP (a, 4096)
  9. static inline grub_err_t
  10. load (grub_file_t file, const char *filename, void *where, grub_off_t off, grub_size_t size)
  11. {
  12. if (grub_file_seek (file, off) == (grub_off_t) -1)
  13. return grub_errno;
  14. if (grub_file_read (file, where, size) != (grub_ssize_t) size)
  15. {
  16. if (grub_errno)
  17. return grub_errno;
  18. return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
  19. filename);
  20. }
  21. return GRUB_ERR_NONE;
  22. }
  23. static inline grub_err_t
  24. read_headers (grub_file_t file, const char *filename, Elf_Ehdr *e, char **shdr)
  25. {
  26. if (grub_file_seek (file, 0) == (grub_off_t) -1)
  27. return grub_errno;
  28. if (grub_file_read (file, (char *) e, sizeof (*e)) != sizeof (*e))
  29. {
  30. if (grub_errno)
  31. return grub_errno;
  32. return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
  33. filename);
  34. }
  35. if (e->e_ident[EI_MAG0] != ELFMAG0
  36. || e->e_ident[EI_MAG1] != ELFMAG1
  37. || e->e_ident[EI_MAG2] != ELFMAG2
  38. || e->e_ident[EI_MAG3] != ELFMAG3
  39. || e->e_ident[EI_VERSION] != EV_CURRENT
  40. || e->e_version != EV_CURRENT)
  41. return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-independent ELF magic"));
  42. if (e->e_ident[EI_CLASS] != SUFFIX (ELFCLASS))
  43. return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-dependent ELF magic"));
  44. *shdr = grub_malloc ((grub_uint32_t) e->e_shnum * e->e_shentsize);
  45. if (! *shdr)
  46. return grub_errno;
  47. if (grub_file_seek (file, e->e_shoff) == (grub_off_t) -1)
  48. return grub_errno;
  49. if (grub_file_read (file, *shdr, (grub_uint32_t) e->e_shnum * e->e_shentsize)
  50. != (grub_ssize_t) ((grub_uint32_t) e->e_shnum * e->e_shentsize))
  51. {
  52. if (grub_errno)
  53. return grub_errno;
  54. return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
  55. filename);
  56. }
  57. return GRUB_ERR_NONE;
  58. }
  59. /* On i386 FreeBSD uses "elf module" approarch for 32-bit variant
  60. and "elf obj module" for 64-bit variant. However it may differ on other
  61. platforms. So I keep both versions. */
  62. #if OBJSYM
  63. grub_err_t
  64. SUFFIX (grub_freebsd_load_elfmodule_obj) (struct grub_relocator *relocator,
  65. grub_file_t file, int argc,
  66. char *argv[], grub_addr_t *kern_end)
  67. {
  68. Elf_Ehdr e;
  69. Elf_Shdr *s;
  70. char *shdr = 0;
  71. grub_addr_t curload, module;
  72. grub_err_t err;
  73. grub_size_t chunk_size = 0;
  74. void *chunk_src;
  75. curload = module = ALIGN_PAGE (*kern_end);
  76. err = read_headers (file, argv[0], &e, &shdr);
  77. if (err)
  78. goto out;
  79. for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) ((char *) shdr
  80. + e.e_shnum * e.e_shentsize);
  81. s = (Elf_Shdr *) ((char *) s + e.e_shentsize))
  82. {
  83. if (s->sh_size == 0)
  84. continue;
  85. if (s->sh_addralign)
  86. chunk_size = ALIGN_UP (chunk_size + *kern_end, s->sh_addralign)
  87. - *kern_end;
  88. chunk_size += s->sh_size;
  89. }
  90. {
  91. grub_relocator_chunk_t ch;
  92. err = grub_relocator_alloc_chunk_addr (relocator, &ch,
  93. module, chunk_size);
  94. if (err)
  95. goto out;
  96. chunk_src = get_virtual_current_address (ch);
  97. }
  98. for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) ((char *) shdr
  99. + e.e_shnum * e.e_shentsize);
  100. s = (Elf_Shdr *) ((char *) s + e.e_shentsize))
  101. {
  102. if (s->sh_size == 0)
  103. continue;
  104. if (s->sh_addralign)
  105. curload = ALIGN_UP (curload, s->sh_addralign);
  106. s->sh_addr = curload;
  107. grub_dprintf ("bsd", "loading section to %x, size %d, align %d\n",
  108. (unsigned) curload, (int) s->sh_size,
  109. (int) s->sh_addralign);
  110. switch (s->sh_type)
  111. {
  112. default:
  113. case SHT_PROGBITS:
  114. err = load (file, argv[0], (grub_uint8_t *) chunk_src + curload - *kern_end,
  115. s->sh_offset, s->sh_size);
  116. if (err)
  117. goto out;
  118. break;
  119. case SHT_NOBITS:
  120. grub_memset ((grub_uint8_t *) chunk_src + curload - *kern_end, 0,
  121. s->sh_size);
  122. break;
  123. }
  124. curload += s->sh_size;
  125. }
  126. *kern_end = ALIGN_PAGE (curload);
  127. err = grub_freebsd_add_meta_module (argv[0], FREEBSD_MODTYPE_ELF_MODULE_OBJ,
  128. argc - 1, argv + 1, module,
  129. curload - module);
  130. if (! err)
  131. err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA
  132. | FREEBSD_MODINFOMD_ELFHDR,
  133. &e, sizeof (e));
  134. if (! err)
  135. err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA
  136. | FREEBSD_MODINFOMD_SHDR,
  137. shdr, e.e_shnum * e.e_shentsize);
  138. out:
  139. grub_free (shdr);
  140. return err;
  141. }
  142. #else
  143. grub_err_t
  144. SUFFIX (grub_freebsd_load_elfmodule) (struct grub_relocator *relocator,
  145. grub_file_t file, int argc, char *argv[],
  146. grub_addr_t *kern_end)
  147. {
  148. Elf_Ehdr e;
  149. Elf_Shdr *s;
  150. char *shdr = 0;
  151. grub_addr_t curload, module;
  152. grub_err_t err;
  153. grub_size_t chunk_size = 0;
  154. void *chunk_src;
  155. curload = module = ALIGN_PAGE (*kern_end);
  156. err = read_headers (file, argv[0], &e, &shdr);
  157. if (err)
  158. goto out;
  159. for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) ((char *) shdr
  160. + e.e_shnum * e.e_shentsize);
  161. s = (Elf_Shdr *) ((char *) s + e.e_shentsize))
  162. {
  163. if (s->sh_size == 0)
  164. continue;
  165. if (! (s->sh_flags & SHF_ALLOC))
  166. continue;
  167. if (chunk_size < s->sh_addr + s->sh_size)
  168. chunk_size = s->sh_addr + s->sh_size;
  169. }
  170. if (chunk_size < sizeof (e))
  171. chunk_size = sizeof (e);
  172. chunk_size += (grub_uint32_t) e.e_phnum * e.e_phentsize;
  173. chunk_size += (grub_uint32_t) e.e_shnum * e.e_shentsize;
  174. {
  175. grub_relocator_chunk_t ch;
  176. err = grub_relocator_alloc_chunk_addr (relocator, &ch,
  177. module, chunk_size);
  178. if (err)
  179. goto out;
  180. chunk_src = get_virtual_current_address (ch);
  181. }
  182. for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) ((char *) shdr
  183. + e.e_shnum * e.e_shentsize);
  184. s = (Elf_Shdr *) ((char *) s + e.e_shentsize))
  185. {
  186. if (s->sh_size == 0)
  187. continue;
  188. if (! (s->sh_flags & SHF_ALLOC))
  189. continue;
  190. grub_dprintf ("bsd", "loading section to %x, size %d, align %d\n",
  191. (unsigned) curload, (int) s->sh_size,
  192. (int) s->sh_addralign);
  193. switch (s->sh_type)
  194. {
  195. default:
  196. case SHT_PROGBITS:
  197. err = load (file, argv[0],
  198. (grub_uint8_t *) chunk_src + module
  199. + s->sh_addr - *kern_end,
  200. s->sh_offset, s->sh_size);
  201. if (err)
  202. goto out;
  203. break;
  204. case SHT_NOBITS:
  205. grub_memset ((grub_uint8_t *) chunk_src + module
  206. + s->sh_addr - *kern_end, 0, s->sh_size);
  207. break;
  208. }
  209. if (curload < module + s->sh_addr + s->sh_size)
  210. curload = module + s->sh_addr + s->sh_size;
  211. }
  212. load (file, argv[0], (grub_uint8_t *) chunk_src + module - *kern_end, 0, sizeof (e));
  213. if (curload < module + sizeof (e))
  214. curload = module + sizeof (e);
  215. load (file, argv[0], (grub_uint8_t *) chunk_src + curload - *kern_end, e.e_shoff,
  216. (grub_uint32_t) e.e_shnum * e.e_shentsize);
  217. e.e_shoff = curload - module;
  218. curload += (grub_uint32_t) e.e_shnum * e.e_shentsize;
  219. load (file, argv[0], (grub_uint8_t *) chunk_src + curload - *kern_end, e.e_phoff,
  220. (grub_uint32_t) e.e_phnum * e.e_phentsize);
  221. e.e_phoff = curload - module;
  222. curload += (grub_uint32_t) e.e_phnum * e.e_phentsize;
  223. *kern_end = curload;
  224. grub_freebsd_add_meta_module (argv[0], FREEBSD_MODTYPE_ELF_MODULE,
  225. argc - 1, argv + 1, module,
  226. curload - module);
  227. out:
  228. grub_free (shdr);
  229. if (err)
  230. return err;
  231. return SUFFIX (grub_freebsd_load_elf_meta) (relocator, file, argv[0], kern_end);
  232. }
  233. #endif
  234. grub_err_t
  235. SUFFIX (grub_freebsd_load_elf_meta) (struct grub_relocator *relocator,
  236. grub_file_t file,
  237. const char *filename,
  238. grub_addr_t *kern_end)
  239. {
  240. grub_err_t err;
  241. Elf_Ehdr e;
  242. Elf_Shdr *s;
  243. char *shdr = 0;
  244. unsigned symoff, stroff, symsize, strsize;
  245. grub_freebsd_addr_t symstart, symend, symentsize, dynamic;
  246. Elf_Sym *sym;
  247. void *sym_chunk;
  248. grub_uint8_t *curload;
  249. grub_freebsd_addr_t symtarget;
  250. const char *str;
  251. unsigned i;
  252. grub_size_t chunk_size;
  253. err = read_headers (file, filename, &e, &shdr);
  254. if (err)
  255. goto out;
  256. err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA |
  257. FREEBSD_MODINFOMD_ELFHDR, &e,
  258. sizeof (e));
  259. if (err)
  260. goto out;
  261. for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) (shdr
  262. + e.e_shnum * e.e_shentsize);
  263. s = (Elf_Shdr *) ((char *) s + e.e_shentsize))
  264. if (s->sh_type == SHT_SYMTAB)
  265. break;
  266. if (s >= (Elf_Shdr *) ((char *) shdr
  267. + e.e_shnum * e.e_shentsize))
  268. {
  269. err = grub_error (GRUB_ERR_BAD_OS, N_("no symbol table"));
  270. goto out;
  271. }
  272. symoff = s->sh_offset;
  273. symsize = s->sh_size;
  274. symentsize = s->sh_entsize;
  275. s = (Elf_Shdr *) (shdr + e.e_shentsize * s->sh_link);
  276. stroff = s->sh_offset;
  277. strsize = s->sh_size;
  278. chunk_size = ALIGN_UP (symsize + strsize, sizeof (grub_freebsd_addr_t))
  279. + 2 * sizeof (grub_freebsd_addr_t);
  280. symtarget = ALIGN_UP (*kern_end, sizeof (grub_freebsd_addr_t));
  281. {
  282. grub_relocator_chunk_t ch;
  283. err = grub_relocator_alloc_chunk_addr (relocator, &ch,
  284. symtarget, chunk_size);
  285. if (err)
  286. goto out;
  287. sym_chunk = get_virtual_current_address (ch);
  288. }
  289. symstart = symtarget;
  290. symend = symstart + chunk_size;
  291. curload = sym_chunk;
  292. *((grub_freebsd_addr_t *) curload) = symsize;
  293. curload += sizeof (grub_freebsd_addr_t);
  294. if (grub_file_seek (file, symoff) == (grub_off_t) -1)
  295. {
  296. err = grub_errno;
  297. goto out;
  298. }
  299. sym = (Elf_Sym *) curload;
  300. if (grub_file_read (file, curload, symsize) != (grub_ssize_t) symsize)
  301. {
  302. if (! grub_errno)
  303. err = grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
  304. filename);
  305. else
  306. err = grub_errno;
  307. goto out;
  308. }
  309. curload += symsize;
  310. *((grub_freebsd_addr_t *) curload) = strsize;
  311. curload += sizeof (grub_freebsd_addr_t);
  312. if (grub_file_seek (file, stroff) == (grub_off_t) -1)
  313. {
  314. err = grub_errno;
  315. goto out;
  316. }
  317. str = (char *) curload;
  318. if (grub_file_read (file, curload, strsize) != (grub_ssize_t) strsize)
  319. {
  320. if (! grub_errno)
  321. err = grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
  322. filename);
  323. else
  324. err = grub_errno;
  325. goto out;
  326. }
  327. for (i = 0;
  328. i * symentsize < symsize;
  329. i++, sym = (Elf_Sym *) ((char *) sym + symentsize))
  330. {
  331. const char *name = str + sym->st_name;
  332. if (grub_strcmp (name, "_DYNAMIC") == 0)
  333. break;
  334. }
  335. if (i * symentsize < symsize)
  336. {
  337. dynamic = sym->st_value;
  338. grub_dprintf ("bsd", "dynamic = %llx\n", (unsigned long long) dynamic);
  339. err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA |
  340. FREEBSD_MODINFOMD_DYNAMIC, &dynamic,
  341. sizeof (dynamic));
  342. if (err)
  343. goto out;
  344. }
  345. err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA |
  346. FREEBSD_MODINFOMD_SSYM, &symstart,
  347. sizeof (symstart));
  348. if (err)
  349. goto out;
  350. err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA |
  351. FREEBSD_MODINFOMD_ESYM, &symend,
  352. sizeof (symend));
  353. out:
  354. grub_free (shdr);
  355. if (err)
  356. return err;
  357. *kern_end = ALIGN_PAGE (symend);
  358. return GRUB_ERR_NONE;
  359. }
  360. grub_err_t
  361. SUFFIX (grub_netbsd_load_elf_meta) (struct grub_relocator *relocator,
  362. grub_file_t file, const char *filename,
  363. grub_addr_t *kern_end)
  364. {
  365. grub_err_t err;
  366. Elf_Ehdr e;
  367. Elf_Shdr *s, *symsh, *strsh;
  368. char *shdr = NULL;
  369. unsigned symsize, strsize;
  370. void *sym_chunk;
  371. grub_uint8_t *curload;
  372. grub_size_t chunk_size;
  373. Elf_Ehdr *e2;
  374. struct grub_netbsd_btinfo_symtab symtab;
  375. grub_addr_t symtarget;
  376. err = read_headers (file, filename, &e, &shdr);
  377. if (err)
  378. {
  379. grub_free (shdr);
  380. return grub_errno;
  381. }
  382. for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) (shdr
  383. + e.e_shnum * e.e_shentsize);
  384. s = (Elf_Shdr *) ((char *) s + e.e_shentsize))
  385. if (s->sh_type == SHT_SYMTAB)
  386. break;
  387. if (s >= (Elf_Shdr *) ((char *) shdr
  388. + e.e_shnum * e.e_shentsize))
  389. {
  390. grub_free (shdr);
  391. return GRUB_ERR_NONE;
  392. }
  393. symsize = s->sh_size;
  394. symsh = s;
  395. s = (Elf_Shdr *) (shdr + e.e_shentsize * s->sh_link);
  396. strsize = s->sh_size;
  397. strsh = s;
  398. chunk_size = ALIGN_UP (symsize, sizeof (grub_freebsd_addr_t))
  399. + ALIGN_UP (strsize, sizeof (grub_freebsd_addr_t))
  400. + sizeof (e) + (grub_uint32_t) e.e_shnum * e.e_shentsize;
  401. symtarget = ALIGN_UP (*kern_end, sizeof (grub_freebsd_addr_t));
  402. {
  403. grub_relocator_chunk_t ch;
  404. err = grub_relocator_alloc_chunk_addr (relocator, &ch,
  405. symtarget, chunk_size);
  406. if (err)
  407. goto out;
  408. sym_chunk = get_virtual_current_address (ch);
  409. }
  410. symtab.nsyms = 1;
  411. symtab.ssyms = symtarget;
  412. symtab.esyms = symtarget + chunk_size;
  413. curload = sym_chunk;
  414. e2 = (Elf_Ehdr *) curload;
  415. grub_memcpy (curload, &e, sizeof (e));
  416. e2->e_phoff = 0;
  417. e2->e_phnum = 0;
  418. e2->e_phentsize = 0;
  419. e2->e_shstrndx = 0;
  420. e2->e_shoff = sizeof (e);
  421. curload += sizeof (e);
  422. for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) (shdr
  423. + e.e_shnum * e.e_shentsize);
  424. s = (Elf_Shdr *) ((char *) s + e.e_shentsize))
  425. {
  426. Elf_Shdr *s2;
  427. s2 = (Elf_Shdr *) curload;
  428. grub_memcpy (curload, s, e.e_shentsize);
  429. if (s == symsh)
  430. s2->sh_offset = sizeof (e) + (grub_uint32_t) e.e_shnum * e.e_shentsize;
  431. else if (s == strsh)
  432. s2->sh_offset = ALIGN_UP (symsize, sizeof (grub_freebsd_addr_t))
  433. + sizeof (e) + (grub_uint32_t) e.e_shnum * e.e_shentsize;
  434. else
  435. s2->sh_offset = 0;
  436. s2->sh_addr = s2->sh_offset;
  437. curload += e.e_shentsize;
  438. }
  439. if (grub_file_seek (file, symsh->sh_offset) == (grub_off_t) -1)
  440. {
  441. err = grub_errno;
  442. goto out;
  443. }
  444. if (grub_file_read (file, curload, symsize) != (grub_ssize_t) symsize)
  445. {
  446. if (! grub_errno)
  447. err = grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
  448. filename);
  449. else
  450. err = grub_errno;
  451. goto out;
  452. }
  453. curload += ALIGN_UP (symsize, sizeof (grub_freebsd_addr_t));
  454. if (grub_file_seek (file, strsh->sh_offset) == (grub_off_t) -1)
  455. {
  456. err = grub_errno;
  457. goto out;
  458. }
  459. if (grub_file_read (file, curload, strsize) != (grub_ssize_t) strsize)
  460. {
  461. if (! grub_errno)
  462. err = grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
  463. filename);
  464. else
  465. err = grub_errno;
  466. goto out;
  467. }
  468. err = grub_bsd_add_meta (NETBSD_BTINFO_SYMTAB,
  469. &symtab,
  470. sizeof (symtab));
  471. out:
  472. grub_free (shdr);
  473. if (err)
  474. return err;
  475. *kern_end = ALIGN_PAGE (symtarget + chunk_size);
  476. return GRUB_ERR_NONE;
  477. }
  478. grub_err_t
  479. SUFFIX(grub_openbsd_find_ramdisk) (grub_file_t file,
  480. const char *filename,
  481. grub_addr_t kern_start,
  482. void *kern_chunk_src,
  483. struct grub_openbsd_ramdisk_descriptor *desc)
  484. {
  485. unsigned symoff, stroff, symsize, strsize, symentsize;
  486. {
  487. grub_err_t err;
  488. Elf_Ehdr e;
  489. Elf_Shdr *s;
  490. char *shdr = NULL;
  491. err = read_headers (file, filename, &e, &shdr);
  492. if (err)
  493. {
  494. grub_free (shdr);
  495. return err;
  496. }
  497. for (s = (Elf_Shdr *) shdr; s < (Elf_Shdr *) (shdr
  498. + e.e_shnum * e.e_shentsize);
  499. s = (Elf_Shdr *) ((char *) s + e.e_shentsize))
  500. if (s->sh_type == SHT_SYMTAB)
  501. break;
  502. if (s >= (Elf_Shdr *) ((char *) shdr + e.e_shnum * e.e_shentsize))
  503. {
  504. grub_free (shdr);
  505. return GRUB_ERR_NONE;
  506. }
  507. symsize = s->sh_size;
  508. symentsize = s->sh_entsize;
  509. symoff = s->sh_offset;
  510. s = (Elf_Shdr *) (shdr + e.e_shentsize * s->sh_link);
  511. stroff = s->sh_offset;
  512. strsize = s->sh_size;
  513. grub_free (shdr);
  514. }
  515. {
  516. Elf_Sym *syms, *sym, *imagesym = NULL, *sizesym = NULL;
  517. unsigned i;
  518. char *strs;
  519. syms = grub_malloc (symsize);
  520. if (!syms)
  521. return grub_errno;
  522. if (grub_file_seek (file, symoff) == (grub_off_t) -1)
  523. {
  524. grub_free (syms);
  525. return grub_errno;
  526. }
  527. if (grub_file_read (file, syms, symsize) != (grub_ssize_t) symsize)
  528. {
  529. grub_free (syms);
  530. if (! grub_errno)
  531. return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
  532. filename);
  533. return grub_errno;
  534. }
  535. strs = grub_malloc (strsize);
  536. if (!strs)
  537. {
  538. grub_free (syms);
  539. return grub_errno;
  540. }
  541. if (grub_file_seek (file, stroff) == (grub_off_t) -1)
  542. {
  543. grub_free (syms);
  544. grub_free (strs);
  545. return grub_errno;
  546. }
  547. if (grub_file_read (file, strs, strsize) != (grub_ssize_t) strsize)
  548. {
  549. grub_free (syms);
  550. grub_free (strs);
  551. if (! grub_errno)
  552. return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
  553. filename);
  554. return grub_errno;
  555. }
  556. for (i = 0, sym = syms; i * symentsize < symsize;
  557. i++, sym = (Elf_Sym *) ((char *) sym + symentsize))
  558. {
  559. if (ELF_ST_TYPE (sym->st_info) != STT_OBJECT)
  560. continue;
  561. if (!sym->st_name)
  562. continue;
  563. if (grub_strcmp (strs + sym->st_name, "rd_root_image") == 0)
  564. imagesym = sym;
  565. if (grub_strcmp (strs + sym->st_name, "rd_root_size") == 0)
  566. sizesym = sym;
  567. if (imagesym && sizesym)
  568. break;
  569. }
  570. if (!imagesym || !sizesym)
  571. {
  572. grub_free (syms);
  573. grub_free (strs);
  574. return GRUB_ERR_NONE;
  575. }
  576. if (sizeof (*desc->size) != sizesym->st_size)
  577. {
  578. grub_free (syms);
  579. grub_free (strs);
  580. return grub_error (GRUB_ERR_BAD_OS, "unexpected size of rd_root_size");
  581. }
  582. desc->max_size = imagesym->st_size;
  583. desc->target = (imagesym->st_value & 0xFFFFFF) - kern_start
  584. + (grub_uint8_t *) kern_chunk_src;
  585. desc->size = (grub_uint32_t *) ((sizesym->st_value & 0xFFFFFF) - kern_start
  586. + (grub_uint8_t *) kern_chunk_src);
  587. grub_free (syms);
  588. grub_free (strs);
  589. return GRUB_ERR_NONE;
  590. }
  591. }