grub-mkimagexx.c 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120
  1. /* grub-mkimage.c - make a bootable image */
  2. /*
  3. * GRUB -- GRand Unified Bootloader
  4. * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc.
  5. *
  6. * GRUB is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * GRUB is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #undef ELF_R_SYM
  20. #undef ELF_R_TYPE
  21. #if defined(MKIMAGE_ELF32)
  22. # define SUFFIX(x) x ## 32
  23. # define ELFCLASSXX ELFCLASS32
  24. # define Elf_Ehdr Elf32_Ehdr
  25. # define Elf_Phdr Elf32_Phdr
  26. # define Elf_Addr Elf32_Addr
  27. # define Elf_Sym Elf32_Sym
  28. # define Elf_Off Elf32_Off
  29. # define Elf_Shdr Elf32_Shdr
  30. # define Elf_Rela Elf32_Rela
  31. # define Elf_Rel Elf32_Rel
  32. # define Elf_Word Elf32_Word
  33. # define Elf_Half Elf32_Half
  34. # define Elf_Section Elf32_Section
  35. # define ELF_R_SYM(val) ELF32_R_SYM(val)
  36. # define ELF_R_TYPE(val) ELF32_R_TYPE(val)
  37. # define ELF_ST_TYPE(val) ELF32_ST_TYPE(val)
  38. #elif defined(MKIMAGE_ELF64)
  39. # define SUFFIX(x) x ## 64
  40. # define ELFCLASSXX ELFCLASS64
  41. # define Elf_Ehdr Elf64_Ehdr
  42. # define Elf_Phdr Elf64_Phdr
  43. # define Elf_Addr Elf64_Addr
  44. # define Elf_Sym Elf64_Sym
  45. # define Elf_Off Elf64_Off
  46. # define Elf_Shdr Elf64_Shdr
  47. # define Elf_Rela Elf64_Rela
  48. # define Elf_Rel Elf64_Rel
  49. # define Elf_Word Elf64_Word
  50. # define Elf_Half Elf64_Half
  51. # define Elf_Section Elf64_Section
  52. # define ELF_R_SYM(val) ELF64_R_SYM(val)
  53. # define ELF_R_TYPE(val) ELF64_R_TYPE(val)
  54. # define ELF_ST_TYPE(val) ELF64_ST_TYPE(val)
  55. #else
  56. #error "I'm confused"
  57. #endif
  58. /* Relocate symbols; note that this function overwrites the symbol table.
  59. Return the address of a start symbol. */
  60. static Elf_Addr
  61. SUFFIX (relocate_symbols) (Elf_Ehdr *e, Elf_Shdr *sections,
  62. Elf_Shdr *symtab_section, Elf_Addr *section_addresses,
  63. Elf_Half section_entsize, Elf_Half num_sections,
  64. void *jumpers, Elf_Addr jumpers_addr,
  65. struct image_target_desc *image_target)
  66. {
  67. Elf_Word symtab_size, sym_size, num_syms;
  68. Elf_Off symtab_offset;
  69. Elf_Addr start_address = 0;
  70. Elf_Sym *sym;
  71. Elf_Word i;
  72. Elf_Shdr *strtab_section;
  73. const char *strtab;
  74. grub_uint64_t *jptr = jumpers;
  75. strtab_section
  76. = (Elf_Shdr *) ((char *) sections
  77. + (grub_target_to_host32 (symtab_section->sh_link)
  78. * section_entsize));
  79. strtab = (char *) e + grub_target_to_host (strtab_section->sh_offset);
  80. symtab_size = grub_target_to_host (symtab_section->sh_size);
  81. sym_size = grub_target_to_host (symtab_section->sh_entsize);
  82. symtab_offset = grub_target_to_host (symtab_section->sh_offset);
  83. num_syms = symtab_size / sym_size;
  84. for (i = 0, sym = (Elf_Sym *) ((char *) e + symtab_offset);
  85. i < num_syms;
  86. i++, sym = (Elf_Sym *) ((char *) sym + sym_size))
  87. {
  88. Elf_Section cur_index;
  89. const char *name;
  90. name = strtab + grub_target_to_host32 (sym->st_name);
  91. cur_index = grub_target_to_host16 (sym->st_shndx);
  92. if (cur_index == STN_ABS)
  93. {
  94. continue;
  95. }
  96. else if ((cur_index == STN_UNDEF))
  97. {
  98. if (sym->st_name)
  99. grub_util_error ("undefined symbol %s", name);
  100. else
  101. continue;
  102. }
  103. else if (cur_index >= num_sections)
  104. grub_util_error ("section %d does not exist", cur_index);
  105. sym->st_value = (grub_target_to_host (sym->st_value)
  106. + section_addresses[cur_index]);
  107. if (image_target->elf_target == EM_IA_64 && ELF_ST_TYPE (sym->st_info)
  108. == STT_FUNC)
  109. {
  110. *jptr = sym->st_value;
  111. sym->st_value = (char *) jptr - (char *) jumpers + jumpers_addr;
  112. jptr++;
  113. *jptr = 0;
  114. jptr++;
  115. }
  116. grub_util_info ("locating %s at 0x%llx (0x%llx)", name,
  117. (unsigned long long) sym->st_value,
  118. (unsigned long long) section_addresses[cur_index]);
  119. if (! start_address)
  120. if (strcmp (name, "_start") == 0 || strcmp (name, "start") == 0)
  121. start_address = sym->st_value;
  122. }
  123. return start_address;
  124. }
  125. /* Return the address of a symbol at the index I in the section S. */
  126. static Elf_Addr
  127. SUFFIX (get_symbol_address) (Elf_Ehdr *e, Elf_Shdr *s, Elf_Word i,
  128. struct image_target_desc *image_target)
  129. {
  130. Elf_Sym *sym;
  131. sym = (Elf_Sym *) ((char *) e
  132. + grub_target_to_host32 (s->sh_offset)
  133. + i * grub_target_to_host32 (s->sh_entsize));
  134. return sym->st_value;
  135. }
  136. /* Return the address of a modified value. */
  137. static Elf_Addr *
  138. SUFFIX (get_target_address) (Elf_Ehdr *e, Elf_Shdr *s, Elf_Addr offset,
  139. struct image_target_desc *image_target)
  140. {
  141. return (Elf_Addr *) ((char *) e + grub_target_to_host32 (s->sh_offset) + offset);
  142. }
  143. #ifdef MKIMAGE_ELF64
  144. static Elf_Addr
  145. SUFFIX (count_funcs) (Elf_Ehdr *e, Elf_Shdr *symtab_section,
  146. struct image_target_desc *image_target)
  147. {
  148. Elf_Word symtab_size, sym_size, num_syms;
  149. Elf_Off symtab_offset;
  150. Elf_Sym *sym;
  151. Elf_Word i;
  152. int ret = 0;
  153. symtab_size = grub_target_to_host (symtab_section->sh_size);
  154. sym_size = grub_target_to_host (symtab_section->sh_entsize);
  155. symtab_offset = grub_target_to_host (symtab_section->sh_offset);
  156. num_syms = symtab_size / sym_size;
  157. for (i = 0, sym = (Elf_Sym *) ((char *) e + symtab_offset);
  158. i < num_syms;
  159. i++, sym = (Elf_Sym *) ((char *) sym + sym_size))
  160. if (ELF_ST_TYPE (sym->st_info) == STT_FUNC)
  161. ret++;
  162. return ret;
  163. }
  164. #endif
  165. #ifdef MKIMAGE_ELF64
  166. struct unaligned_uint32
  167. {
  168. grub_uint32_t val;
  169. } __attribute__ ((packed));
  170. #define MASK20 ((1 << 20) - 1)
  171. #define MASK19 ((1 << 19) - 1)
  172. #define MASK3 (~(grub_addr_t) 3)
  173. static void
  174. add_value_to_slot_20b (grub_addr_t addr, grub_uint32_t value)
  175. {
  176. struct unaligned_uint32 *p;
  177. switch (addr & 3)
  178. {
  179. case 0:
  180. p = (struct unaligned_uint32 *) ((addr & MASK3) + 2);
  181. p->val = ((((((p->val >> 2) & MASK20) + value) & MASK20) << 2)
  182. | (p->val & ~(MASK20 << 2)));
  183. break;
  184. case 1:
  185. p = (struct unaligned_uint32 *) ((grub_uint8_t *) (addr & MASK3) + 7);
  186. p->val = ((((((p->val >> 3) & MASK20) + value) & MASK20) << 3)
  187. | (p->val & ~(MASK20 << 3)));
  188. break;
  189. case 2:
  190. p = (struct unaligned_uint32 *) ((grub_uint8_t *) (addr & MASK3) + 12);
  191. p->val = ((((((p->val >> 4) & MASK20) + value) & MASK20) << 4)
  192. | (p->val & ~(MASK20 << 4)));
  193. break;
  194. }
  195. }
  196. #define MASKF21 ( ((1 << 23) - 1) & ~((1 << 7) | (1 << 8)) )
  197. static grub_uint32_t
  198. add_value_to_slot_21_real (grub_uint32_t a, grub_uint32_t value)
  199. {
  200. grub_uint32_t high, mid, low, c;
  201. low = (a & 0x00007f);
  202. mid = (a & 0x7fc000) >> 7;
  203. high = (a & 0x003e00) << 7;
  204. c = (low | mid | high) + value;
  205. return (c & 0x7f) | ((c << 7) & 0x7fc000) | ((c >> 7) & 0x0003e00); //0x003e00
  206. }
  207. static void
  208. add_value_to_slot_21 (grub_addr_t addr, grub_uint32_t value)
  209. {
  210. struct unaligned_uint32 *p;
  211. switch (addr & 3)
  212. {
  213. case 0:
  214. p = (struct unaligned_uint32 *) ((addr & MASK3) + 2);
  215. p->val = ((add_value_to_slot_21_real (((p->val >> 2) & MASKF21), value) & MASKF21) << 2) | (p->val & ~(MASKF21 << 2));
  216. break;
  217. case 1:
  218. p = (struct unaligned_uint32 *) ((grub_uint8_t *) (addr & MASK3) + 7);
  219. p->val = ((add_value_to_slot_21_real (((p->val >> 3) & MASKF21), value) & MASKF21) << 3) | (p->val & ~(MASKF21 << 3));
  220. break;
  221. case 2:
  222. p = (struct unaligned_uint32 *) ((grub_uint8_t *) (addr & MASK3) + 12);
  223. p->val = ((add_value_to_slot_21_real (((p->val >> 4) & MASKF21), value) & MASKF21) << 4) | (p->val & ~(MASKF21 << 4));
  224. break;
  225. }
  226. }
  227. struct ia64_kernel_trampoline
  228. {
  229. /* nop.m */
  230. grub_uint8_t nop[5];
  231. /* movl r15 = addr*/
  232. grub_uint8_t addr_hi[6];
  233. grub_uint8_t e0;
  234. grub_uint8_t addr_lo[4];
  235. grub_uint8_t jump[0x20];
  236. };
  237. static grub_uint8_t nopm[5] =
  238. {
  239. /* [MLX] nop.m 0x0 */
  240. 0x05, 0x00, 0x00, 0x00, 0x01
  241. };
  242. static grub_uint8_t jump[0x20] =
  243. {
  244. /* [MMI] add r15=r15,r1;; */
  245. 0x0b, 0x78, 0x3c, 0x02, 0x00, 0x20,
  246. /* ld8 r16=[r15],8 */
  247. 0x00, 0x41, 0x3c, 0x30, 0x28, 0xc0,
  248. /* mov r14=r1;; */
  249. 0x01, 0x08, 0x00, 0x84,
  250. /* [MIB] ld8 r1=[r15] */
  251. 0x11, 0x08, 0x00, 0x1e, 0x18, 0x10,
  252. /* mov b6=r16 */
  253. 0x60, 0x80, 0x04, 0x80, 0x03, 0x00,
  254. /* br.few b6;; */
  255. 0x60, 0x00, 0x80, 0x00
  256. };
  257. static void
  258. make_trampoline (struct ia64_kernel_trampoline *tr, grub_uint64_t addr)
  259. {
  260. grub_memcpy (tr->nop, nopm, sizeof (tr->nop));
  261. tr->addr_hi[0] = ((addr & 0xc00000) >> 16);
  262. tr->addr_hi[1] = (addr >> 24) & 0xff;
  263. tr->addr_hi[2] = (addr >> 32) & 0xff;
  264. tr->addr_hi[3] = (addr >> 40) & 0xff;
  265. tr->addr_hi[4] = (addr >> 48) & 0xff;
  266. tr->addr_hi[5] = (addr >> 56) & 0xff;
  267. tr->e0 = 0xe0;
  268. tr->addr_lo[0] = ((addr & 0x000f) << 4) | 0x01;
  269. tr->addr_lo[1] = (((addr & 0x0070) >> 4) | ((addr & 0x070000) >> 11)
  270. | ((addr & 0x200000) >> 17));
  271. tr->addr_lo[2] = ((addr & 0x1f80) >> 5) | ((addr & 0x180000) >> 19);
  272. tr->addr_lo[3] = ((addr & 0xe000) >> 13) | 0x60;
  273. grub_memcpy (tr->jump, jump, sizeof (tr->jump));
  274. }
  275. #endif
  276. /* Deal with relocation information. This function relocates addresses
  277. within the virtual address space starting from 0. So only relative
  278. addresses can be fully resolved. Absolute addresses must be relocated
  279. again by a PE32 relocator when loaded. */
  280. static void
  281. SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections,
  282. Elf_Addr *section_addresses,
  283. Elf_Half section_entsize, Elf_Half num_sections,
  284. const char *strtab,
  285. char *pe_target, Elf_Addr tramp_off,
  286. Elf_Addr got_off,
  287. struct image_target_desc *image_target)
  288. {
  289. Elf_Half i;
  290. Elf_Shdr *s;
  291. #ifdef MKIMAGE_ELF64
  292. struct ia64_kernel_trampoline *tr = (void *) (pe_target + tramp_off);
  293. grub_uint64_t *gpptr = (void *) (pe_target + got_off);
  294. #endif
  295. for (i = 0, s = sections;
  296. i < num_sections;
  297. i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
  298. if ((s->sh_type == grub_host_to_target32 (SHT_REL)) ||
  299. (s->sh_type == grub_host_to_target32 (SHT_RELA)))
  300. {
  301. Elf_Rela *r;
  302. Elf_Word rtab_size, r_size, num_rs;
  303. Elf_Off rtab_offset;
  304. Elf_Shdr *symtab_section;
  305. Elf_Word target_section_index;
  306. Elf_Addr target_section_addr;
  307. Elf_Shdr *target_section;
  308. Elf_Word j;
  309. symtab_section = (Elf_Shdr *) ((char *) sections
  310. + (grub_target_to_host32 (s->sh_link)
  311. * section_entsize));
  312. target_section_index = grub_target_to_host32 (s->sh_info);
  313. target_section_addr = section_addresses[target_section_index];
  314. target_section = (Elf_Shdr *) ((char *) sections
  315. + (target_section_index
  316. * section_entsize));
  317. grub_util_info ("dealing with the relocation section %s for %s",
  318. strtab + grub_target_to_host32 (s->sh_name),
  319. strtab + grub_target_to_host32 (target_section->sh_name));
  320. rtab_size = grub_target_to_host32 (s->sh_size);
  321. r_size = grub_target_to_host32 (s->sh_entsize);
  322. rtab_offset = grub_target_to_host32 (s->sh_offset);
  323. num_rs = rtab_size / r_size;
  324. for (j = 0, r = (Elf_Rela *) ((char *) e + rtab_offset);
  325. j < num_rs;
  326. j++, r = (Elf_Rela *) ((char *) r + r_size))
  327. {
  328. Elf_Addr info;
  329. Elf_Addr offset;
  330. Elf_Addr sym_addr;
  331. Elf_Addr *target;
  332. Elf_Addr addend;
  333. offset = grub_target_to_host (r->r_offset);
  334. target = SUFFIX (get_target_address) (e, target_section,
  335. offset, image_target);
  336. info = grub_target_to_host (r->r_info);
  337. sym_addr = SUFFIX (get_symbol_address) (e, symtab_section,
  338. ELF_R_SYM (info), image_target);
  339. addend = (s->sh_type == grub_target_to_host32 (SHT_RELA)) ?
  340. r->r_addend : 0;
  341. switch (image_target->elf_target)
  342. {
  343. case EM_386:
  344. switch (ELF_R_TYPE (info))
  345. {
  346. case R_386_NONE:
  347. break;
  348. case R_386_32:
  349. /* This is absolute. */
  350. *target = grub_host_to_target32 (grub_target_to_host32 (*target)
  351. + addend + sym_addr);
  352. grub_util_info ("relocating an R_386_32 entry to 0x%llx at the offset 0x%llx",
  353. (unsigned long long) *target,
  354. (unsigned long long) offset);
  355. break;
  356. case R_386_PC32:
  357. /* This is relative. */
  358. *target = grub_host_to_target32 (grub_target_to_host32 (*target)
  359. + addend + sym_addr
  360. - target_section_addr - offset
  361. - image_target->vaddr_offset);
  362. grub_util_info ("relocating an R_386_PC32 entry to 0x%llx at the offset 0x%llx",
  363. (unsigned long long) *target,
  364. (unsigned long long) offset);
  365. break;
  366. default:
  367. grub_util_error (_("relocation 0x%x is not implemented yet"),
  368. ELF_R_TYPE (info));
  369. break;
  370. }
  371. break;
  372. #ifdef MKIMAGE_ELF64
  373. case EM_X86_64:
  374. switch (ELF_R_TYPE (info))
  375. {
  376. case R_X86_64_NONE:
  377. break;
  378. case R_X86_64_64:
  379. *target = grub_host_to_target64 (grub_target_to_host64 (*target)
  380. + addend + sym_addr);
  381. grub_util_info ("relocating an R_X86_64_64 entry to 0x%llx at the offset 0x%llx",
  382. (unsigned long long) *target,
  383. (unsigned long long) offset);
  384. break;
  385. case R_X86_64_PC32:
  386. {
  387. grub_uint32_t *t32 = (grub_uint32_t *) target;
  388. *t32 = grub_host_to_target64 (grub_target_to_host32 (*t32)
  389. + addend + sym_addr
  390. - target_section_addr - offset
  391. - image_target->vaddr_offset);
  392. grub_util_info ("relocating an R_X86_64_PC32 entry to 0x%x at the offset 0x%llx",
  393. *t32, (unsigned long long) offset);
  394. break;
  395. }
  396. case R_X86_64_32:
  397. case R_X86_64_32S:
  398. {
  399. grub_uint32_t *t32 = (grub_uint32_t *) target;
  400. *t32 = grub_host_to_target64 (grub_target_to_host32 (*t32)
  401. + addend + sym_addr);
  402. grub_util_info ("relocating an R_X86_64_32(S) entry to 0x%x at the offset 0x%llx",
  403. *t32, (unsigned long long) offset);
  404. break;
  405. }
  406. default:
  407. grub_util_error (_("relocation 0x%x is not implemented yet"),
  408. ELF_R_TYPE (info));
  409. break;
  410. }
  411. break;
  412. case EM_IA_64:
  413. switch (ELF_R_TYPE (info))
  414. {
  415. case R_IA64_PCREL21B:
  416. {
  417. grub_uint64_t noff;
  418. make_trampoline (tr, addend + sym_addr);
  419. noff = ((char *) tr - (char *) pe_target
  420. - target_section_addr - (offset & ~3)) >> 4;
  421. tr++;
  422. if (noff & ~MASK19)
  423. grub_util_error ("trampoline offset too big (%"
  424. PRIxGRUB_UINT64_T ")", noff);
  425. add_value_to_slot_20b ((grub_addr_t) target, noff);
  426. }
  427. break;
  428. case R_IA64_LTOFF22X:
  429. case R_IA64_LTOFF22:
  430. {
  431. Elf_Sym *sym;
  432. sym = (Elf_Sym *) ((char *) e
  433. + grub_target_to_host32 (symtab_section->sh_offset)
  434. + ELF_R_SYM (info) * grub_target_to_host32 (symtab_section->sh_entsize));
  435. if (ELF_ST_TYPE (sym->st_info) == STT_FUNC)
  436. sym_addr = grub_target_to_host64 (*(grub_uint64_t *) (pe_target
  437. + sym->st_value
  438. - image_target->vaddr_offset));
  439. }
  440. case R_IA64_LTOFF_FPTR22:
  441. *gpptr = grub_host_to_target64 (addend + sym_addr);
  442. add_value_to_slot_21 ((grub_addr_t) target,
  443. (char *) gpptr - (char *) pe_target
  444. + image_target->vaddr_offset);
  445. gpptr++;
  446. break;
  447. case R_IA64_GPREL22:
  448. add_value_to_slot_21 ((grub_addr_t) target,
  449. addend + sym_addr);
  450. break;
  451. case R_IA64_PCREL64LSB:
  452. *target = grub_host_to_target64 (grub_target_to_host64 (*target)
  453. + addend + sym_addr
  454. - target_section_addr - offset
  455. - image_target->vaddr_offset);
  456. break;
  457. case R_IA64_SEGREL64LSB:
  458. *target = grub_host_to_target64 (grub_target_to_host64 (*target)
  459. + addend + sym_addr - target_section_addr);
  460. break;
  461. case R_IA64_DIR64LSB:
  462. case R_IA64_FPTR64LSB:
  463. *target = grub_host_to_target64 (grub_target_to_host64 (*target)
  464. + addend + sym_addr);
  465. grub_util_info ("relocating a direct entry to 0x%"
  466. PRIxGRUB_UINT64_T " at the offset 0x%llx",
  467. *target, (unsigned long long) offset);
  468. break;
  469. /* We treat LTOFF22X as LTOFF22, so we can ignore LDXMOV. */
  470. case R_IA64_LDXMOV:
  471. break;
  472. default:
  473. grub_util_error (_("relocation 0x%x is not implemented yet"),
  474. ELF_R_TYPE (info));
  475. break;
  476. }
  477. break;
  478. #endif
  479. default:
  480. grub_util_error ("unknown architecture type %d",
  481. image_target->elf_target);
  482. }
  483. }
  484. }
  485. }
  486. /* Add a PE32's fixup entry for a relocation. Return the resulting address
  487. after having written to the file OUT. */
  488. static Elf_Addr
  489. SUFFIX (add_fixup_entry) (struct fixup_block_list **cblock, grub_uint16_t type,
  490. Elf_Addr addr, int flush, Elf_Addr current_address,
  491. struct image_target_desc *image_target)
  492. {
  493. struct grub_pe32_fixup_block *b;
  494. b = &((*cblock)->b);
  495. /* First, check if it is necessary to write out the current block. */
  496. if ((*cblock)->state)
  497. {
  498. if (flush || addr < b->page_rva || b->page_rva + 0x1000 <= addr)
  499. {
  500. grub_uint32_t size;
  501. if (flush)
  502. {
  503. /* Add as much padding as necessary to align the address
  504. with a section boundary. */
  505. Elf_Addr next_address;
  506. unsigned padding_size;
  507. size_t cur_index;
  508. next_address = current_address + b->block_size;
  509. padding_size = ((ALIGN_UP (next_address, image_target->section_align)
  510. - next_address)
  511. >> 1);
  512. cur_index = ((b->block_size - sizeof (*b)) >> 1);
  513. grub_util_info ("adding %d padding fixup entries", padding_size);
  514. while (padding_size--)
  515. {
  516. b->entries[cur_index++] = 0;
  517. b->block_size += 2;
  518. }
  519. }
  520. else while (b->block_size & (8 - 1))
  521. {
  522. /* If not aligned with a 32-bit boundary, add
  523. a padding entry. */
  524. size_t cur_index;
  525. grub_util_info ("adding a padding fixup entry");
  526. cur_index = ((b->block_size - sizeof (*b)) >> 1);
  527. b->entries[cur_index] = 0;
  528. b->block_size += 2;
  529. }
  530. /* Flush it. */
  531. grub_util_info ("writing %d bytes of a fixup block starting at 0x%x",
  532. b->block_size, b->page_rva);
  533. size = b->block_size;
  534. current_address += size;
  535. b->page_rva = grub_host_to_target32 (b->page_rva);
  536. b->block_size = grub_host_to_target32 (b->block_size);
  537. (*cblock)->next = xmalloc (sizeof (**cblock) + 2 * 0x1000);
  538. memset ((*cblock)->next, 0, sizeof (**cblock) + 2 * 0x1000);
  539. *cblock = (*cblock)->next;
  540. }
  541. }
  542. b = &((*cblock)->b);
  543. if (! flush)
  544. {
  545. grub_uint16_t entry;
  546. size_t cur_index;
  547. /* If not allocated yet, allocate a block with enough entries. */
  548. if (! (*cblock)->state)
  549. {
  550. (*cblock)->state = 1;
  551. /* The spec does not mention the requirement of a Page RVA.
  552. Here, align the address with a 4K boundary for safety. */
  553. b->page_rva = (addr & ~(0x1000 - 1));
  554. b->block_size = sizeof (*b);
  555. }
  556. /* Sanity check. */
  557. if (b->block_size >= sizeof (*b) + 2 * 0x1000)
  558. grub_util_error ("too many fixup entries");
  559. /* Add a new entry. */
  560. cur_index = ((b->block_size - sizeof (*b)) >> 1);
  561. entry = GRUB_PE32_FIXUP_ENTRY (type, addr - b->page_rva);
  562. b->entries[cur_index] = grub_host_to_target16 (entry);
  563. b->block_size += 2;
  564. }
  565. return current_address;
  566. }
  567. /* Make a .reloc section. */
  568. static Elf_Addr
  569. SUFFIX (make_reloc_section) (Elf_Ehdr *e, void **out,
  570. Elf_Addr *section_addresses, Elf_Shdr *sections,
  571. Elf_Half section_entsize, Elf_Half num_sections,
  572. const char *strtab,
  573. Elf_Addr jumpers, grub_size_t njumpers,
  574. struct image_target_desc *image_target)
  575. {
  576. unsigned i;
  577. Elf_Shdr *s;
  578. struct fixup_block_list *lst, *lst0;
  579. Elf_Addr current_address = 0;
  580. lst = lst0 = xmalloc (sizeof (*lst) + 2 * 0x1000);
  581. memset (lst, 0, sizeof (*lst) + 2 * 0x1000);
  582. for (i = 0, s = sections; i < num_sections;
  583. i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
  584. if ((s->sh_type == grub_cpu_to_le32 (SHT_REL)) ||
  585. (s->sh_type == grub_cpu_to_le32 (SHT_RELA)))
  586. {
  587. Elf_Rel *r;
  588. Elf_Word rtab_size, r_size, num_rs;
  589. Elf_Off rtab_offset;
  590. Elf_Addr section_address;
  591. Elf_Word j;
  592. grub_util_info ("translating the relocation section %s",
  593. strtab + grub_le_to_cpu32 (s->sh_name));
  594. rtab_size = grub_le_to_cpu32 (s->sh_size);
  595. r_size = grub_le_to_cpu32 (s->sh_entsize);
  596. rtab_offset = grub_le_to_cpu32 (s->sh_offset);
  597. num_rs = rtab_size / r_size;
  598. section_address = section_addresses[grub_le_to_cpu32 (s->sh_info)];
  599. for (j = 0, r = (Elf_Rel *) ((char *) e + rtab_offset);
  600. j < num_rs;
  601. j++, r = (Elf_Rel *) ((char *) r + r_size))
  602. {
  603. Elf_Addr info;
  604. Elf_Addr offset;
  605. offset = grub_le_to_cpu32 (r->r_offset);
  606. info = grub_le_to_cpu32 (r->r_info);
  607. /* Necessary to relocate only absolute addresses. */
  608. switch (image_target->elf_target)
  609. {
  610. case EM_386:
  611. if (ELF_R_TYPE (info) == R_386_32)
  612. {
  613. Elf_Addr addr;
  614. addr = section_address + offset;
  615. grub_util_info ("adding a relocation entry for 0x%llx",
  616. (unsigned long long) addr);
  617. current_address
  618. = SUFFIX (add_fixup_entry) (&lst,
  619. GRUB_PE32_REL_BASED_HIGHLOW,
  620. addr, 0, current_address,
  621. image_target);
  622. }
  623. break;
  624. case EM_X86_64:
  625. if ((ELF_R_TYPE (info) == R_X86_64_32) ||
  626. (ELF_R_TYPE (info) == R_X86_64_32S))
  627. {
  628. grub_util_error ("can\'t add fixup entry for R_X86_64_32(S)");
  629. }
  630. else if (ELF_R_TYPE (info) == R_X86_64_64)
  631. {
  632. Elf_Addr addr;
  633. addr = section_address + offset;
  634. grub_util_info ("adding a relocation entry for 0x%llx",
  635. (unsigned long long) addr);
  636. current_address
  637. = SUFFIX (add_fixup_entry) (&lst,
  638. GRUB_PE32_REL_BASED_DIR64,
  639. addr,
  640. 0, current_address,
  641. image_target);
  642. }
  643. break;
  644. case EM_IA_64:
  645. switch (ELF_R_TYPE (info))
  646. {
  647. case R_IA64_PCREL64LSB:
  648. case R_IA64_LDXMOV:
  649. case R_IA64_PCREL21B:
  650. case R_IA64_LTOFF_FPTR22:
  651. case R_IA64_LTOFF22X:
  652. case R_IA64_LTOFF22:
  653. case R_IA64_GPREL22:
  654. case R_IA64_SEGREL64LSB:
  655. break;
  656. case R_IA64_FPTR64LSB:
  657. case R_IA64_DIR64LSB:
  658. #if 1
  659. {
  660. Elf_Addr addr;
  661. addr = section_address + offset;
  662. grub_util_info ("adding a relocation entry for 0x%llx",
  663. (unsigned long long) addr);
  664. current_address
  665. = SUFFIX (add_fixup_entry) (&lst,
  666. GRUB_PE32_REL_BASED_DIR64,
  667. addr,
  668. 0, current_address,
  669. image_target);
  670. }
  671. #endif
  672. break;
  673. default:
  674. grub_util_error (_("relocation 0x%x is not implemented yet"),
  675. ELF_R_TYPE (info));
  676. break;
  677. }
  678. break;
  679. default:
  680. grub_util_error ("unknown machine type 0x%x", image_target->elf_target);
  681. }
  682. }
  683. }
  684. if (image_target->elf_target == EM_IA_64)
  685. for (i = 0; i < njumpers; i++)
  686. current_address = SUFFIX (add_fixup_entry) (&lst,
  687. GRUB_PE32_REL_BASED_DIR64,
  688. jumpers + 8 * i,
  689. 0, current_address,
  690. image_target);
  691. current_address = SUFFIX (add_fixup_entry) (&lst, 0, 0, 1, current_address, image_target);
  692. {
  693. grub_uint8_t *ptr;
  694. ptr = *out = xmalloc (current_address);
  695. for (lst = lst0; lst; lst = lst->next)
  696. if (lst->state)
  697. {
  698. memcpy (ptr, &lst->b, grub_target_to_host32 (lst->b.block_size));
  699. ptr += grub_target_to_host32 (lst->b.block_size);
  700. }
  701. assert ((current_address + (grub_uint8_t *) *out) == ptr);
  702. }
  703. return current_address;
  704. }
  705. /* Determine if this section is a text section. Return false if this
  706. section is not allocated. */
  707. static int
  708. SUFFIX (is_text_section) (Elf_Shdr *s, struct image_target_desc *image_target)
  709. {
  710. if (image_target->id != IMAGE_EFI
  711. && grub_target_to_host32 (s->sh_type) != SHT_PROGBITS)
  712. return 0;
  713. return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
  714. == (SHF_EXECINSTR | SHF_ALLOC));
  715. }
  716. /* Determine if this section is a data section. This assumes that
  717. BSS is also a data section, since the converter initializes BSS
  718. when producing PE32 to avoid a bug in EFI implementations. */
  719. static int
  720. SUFFIX (is_data_section) (Elf_Shdr *s, struct image_target_desc *image_target)
  721. {
  722. if (image_target->id != IMAGE_EFI
  723. && grub_target_to_host32 (s->sh_type) != SHT_PROGBITS)
  724. return 0;
  725. return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
  726. == SHF_ALLOC);
  727. }
  728. /* Return if the ELF header is valid. */
  729. static int
  730. SUFFIX (check_elf_header) (Elf_Ehdr *e, size_t size, struct image_target_desc *image_target)
  731. {
  732. if (size < sizeof (*e)
  733. || e->e_ident[EI_MAG0] != ELFMAG0
  734. || e->e_ident[EI_MAG1] != ELFMAG1
  735. || e->e_ident[EI_MAG2] != ELFMAG2
  736. || e->e_ident[EI_MAG3] != ELFMAG3
  737. || e->e_ident[EI_VERSION] != EV_CURRENT
  738. || e->e_ident[EI_CLASS] != ELFCLASSXX
  739. || e->e_version != grub_host_to_target32 (EV_CURRENT))
  740. return 0;
  741. return 1;
  742. }
  743. /* Locate section addresses by merging code sections and data sections
  744. into .text and .data, respectively. Return the array of section
  745. addresses. */
  746. static Elf_Addr *
  747. SUFFIX (locate_sections) (Elf_Shdr *sections, Elf_Half section_entsize,
  748. Elf_Half num_sections, const char *strtab,
  749. grub_size_t *exec_size, grub_size_t *kernel_sz,
  750. grub_size_t *all_align,
  751. struct image_target_desc *image_target)
  752. {
  753. int i;
  754. Elf_Addr current_address;
  755. Elf_Addr *section_addresses;
  756. Elf_Shdr *s;
  757. *all_align = 1;
  758. section_addresses = xmalloc (sizeof (*section_addresses) * num_sections);
  759. memset (section_addresses, 0, sizeof (*section_addresses) * num_sections);
  760. current_address = 0;
  761. for (i = 0, s = sections;
  762. i < num_sections;
  763. i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
  764. if ((grub_target_to_host (s->sh_flags) & SHF_ALLOC)
  765. && grub_host_to_target32 (s->sh_addralign) > *all_align)
  766. *all_align = grub_host_to_target32 (s->sh_addralign);
  767. /* .text */
  768. for (i = 0, s = sections;
  769. i < num_sections;
  770. i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
  771. if (SUFFIX (is_text_section) (s, image_target))
  772. {
  773. Elf_Word align = grub_host_to_target_addr (s->sh_addralign);
  774. const char *name = strtab + grub_host_to_target32 (s->sh_name);
  775. if (align)
  776. current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
  777. align) - image_target->vaddr_offset;
  778. grub_util_info ("locating the section %s at 0x%llx",
  779. name, (unsigned long long) current_address);
  780. if (image_target->id != IMAGE_EFI)
  781. current_address = grub_host_to_target_addr (s->sh_addr)
  782. - image_target->link_addr;
  783. section_addresses[i] = current_address;
  784. current_address += grub_host_to_target_addr (s->sh_size);
  785. }
  786. current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
  787. image_target->section_align)
  788. - image_target->vaddr_offset;
  789. *exec_size = current_address;
  790. /* .data */
  791. for (i = 0, s = sections;
  792. i < num_sections;
  793. i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
  794. if (SUFFIX (is_data_section) (s, image_target))
  795. {
  796. Elf_Word align = grub_host_to_target_addr (s->sh_addralign);
  797. const char *name = strtab + grub_host_to_target32 (s->sh_name);
  798. if (align)
  799. current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
  800. align)
  801. - image_target->vaddr_offset;
  802. grub_util_info ("locating the section %s at 0x%llx",
  803. name, (unsigned long long) current_address);
  804. if (image_target->id != IMAGE_EFI)
  805. current_address = grub_host_to_target_addr (s->sh_addr)
  806. - image_target->link_addr;
  807. section_addresses[i] = current_address;
  808. current_address += grub_host_to_target_addr (s->sh_size);
  809. }
  810. current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
  811. image_target->section_align) - image_target->vaddr_offset;
  812. *kernel_sz = current_address;
  813. return section_addresses;
  814. }
  815. static char *
  816. SUFFIX (load_image) (const char *kernel_path, grub_size_t *exec_size,
  817. grub_size_t *kernel_sz, grub_size_t *bss_size,
  818. grub_size_t total_module_size, grub_uint64_t *start,
  819. void **reloc_section, grub_size_t *reloc_size,
  820. grub_size_t *align,
  821. struct image_target_desc *image_target)
  822. {
  823. char *kernel_img, *out_img;
  824. const char *strtab;
  825. Elf_Ehdr *e;
  826. Elf_Shdr *sections;
  827. Elf_Addr *section_addresses;
  828. Elf_Addr *section_vaddresses;
  829. int i;
  830. Elf_Shdr *s;
  831. Elf_Half num_sections;
  832. Elf_Off section_offset;
  833. Elf_Half section_entsize;
  834. grub_size_t kernel_size;
  835. grub_size_t ia64jmp_off = 0, ia64_toff = 0, ia64_got_off = 0;
  836. unsigned ia64jmpnum = 0;
  837. Elf_Shdr *symtab_section = 0;
  838. grub_size_t got = 0;
  839. *start = 0;
  840. kernel_size = grub_util_get_image_size (kernel_path);
  841. kernel_img = xmalloc (kernel_size);
  842. grub_util_load_image (kernel_path, kernel_img);
  843. e = (Elf_Ehdr *) kernel_img;
  844. if (! SUFFIX (check_elf_header) (e, kernel_size, image_target))
  845. grub_util_error ("invalid ELF header");
  846. section_offset = grub_target_to_host (e->e_shoff);
  847. section_entsize = grub_target_to_host16 (e->e_shentsize);
  848. num_sections = grub_target_to_host16 (e->e_shnum);
  849. if (kernel_size < section_offset + section_entsize * num_sections)
  850. grub_util_error (_("premature end of file %s"), kernel_path);
  851. sections = (Elf_Shdr *) (kernel_img + section_offset);
  852. /* Relocate sections then symbols in the virtual address space. */
  853. s = (Elf_Shdr *) ((char *) sections
  854. + grub_host_to_target16 (e->e_shstrndx) * section_entsize);
  855. strtab = (char *) e + grub_host_to_target_addr (s->sh_offset);
  856. section_addresses = SUFFIX (locate_sections) (sections, section_entsize,
  857. num_sections, strtab,
  858. exec_size, kernel_sz, align,
  859. image_target);
  860. section_vaddresses = xmalloc (sizeof (*section_addresses) * num_sections);
  861. for (i = 0; i < num_sections; i++)
  862. section_vaddresses[i] = section_addresses[i] + image_target->vaddr_offset;
  863. if (image_target->id != IMAGE_EFI)
  864. {
  865. Elf_Addr current_address = *kernel_sz;
  866. for (i = 0, s = sections;
  867. i < num_sections;
  868. i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
  869. if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS)
  870. {
  871. Elf_Word sec_align = grub_host_to_target_addr (s->sh_addralign);
  872. const char *name = strtab + grub_host_to_target32 (s->sh_name);
  873. if (sec_align)
  874. current_address = ALIGN_UP (current_address
  875. + image_target->vaddr_offset,
  876. sec_align)
  877. - image_target->vaddr_offset;
  878. grub_util_info ("locating the section %s at 0x%llx",
  879. name, (unsigned long long) current_address);
  880. if (image_target->id != IMAGE_EFI)
  881. current_address = grub_host_to_target_addr (s->sh_addr)
  882. - image_target->link_addr;
  883. section_vaddresses[i] = current_address
  884. + image_target->vaddr_offset;
  885. current_address += grub_host_to_target_addr (s->sh_size);
  886. }
  887. current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
  888. image_target->section_align)
  889. - image_target->vaddr_offset;
  890. *bss_size = current_address - *kernel_sz;
  891. }
  892. else
  893. *bss_size = 0;
  894. if (image_target->id == IMAGE_EFI)
  895. {
  896. symtab_section = NULL;
  897. for (i = 0, s = sections;
  898. i < num_sections;
  899. i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
  900. if (s->sh_type == grub_host_to_target32 (SHT_SYMTAB))
  901. {
  902. symtab_section = s;
  903. break;
  904. }
  905. #ifdef MKIMAGE_ELF64
  906. if (image_target->elf_target == EM_IA_64)
  907. {
  908. grub_size_t tramp;
  909. *kernel_sz = ALIGN_UP (*kernel_sz, 16);
  910. grub_ia64_dl_get_tramp_got_size (e, &tramp, &got);
  911. tramp *= sizeof (struct ia64_kernel_trampoline);
  912. ia64_toff = *kernel_sz;
  913. *kernel_sz += ALIGN_UP (tramp, 16);
  914. ia64jmp_off = *kernel_sz;
  915. ia64jmpnum = SUFFIX (count_funcs) (e, symtab_section,
  916. image_target);
  917. *kernel_sz += 16 * ia64jmpnum;
  918. ia64_got_off = *kernel_sz;
  919. *kernel_sz += ALIGN_UP (got * sizeof (grub_uint64_t), 16);
  920. }
  921. #endif
  922. if (! symtab_section)
  923. grub_util_error ("%s", _("no symbol table"));
  924. }
  925. else
  926. {
  927. *reloc_size = 0;
  928. *reloc_section = NULL;
  929. }
  930. out_img = xmalloc (*kernel_sz + total_module_size);
  931. if (image_target->id == IMAGE_EFI)
  932. {
  933. *start = SUFFIX (relocate_symbols) (e, sections, symtab_section,
  934. section_vaddresses, section_entsize,
  935. num_sections,
  936. (char *) out_img + ia64jmp_off,
  937. ia64jmp_off
  938. + image_target->vaddr_offset,
  939. image_target);
  940. if (*start == 0)
  941. grub_util_error ("start symbol is not defined");
  942. /* Resolve addresses in the virtual address space. */
  943. SUFFIX (relocate_addresses) (e, sections, section_addresses,
  944. section_entsize,
  945. num_sections, strtab,
  946. out_img, ia64_toff, ia64_got_off,
  947. image_target);
  948. *reloc_size = SUFFIX (make_reloc_section) (e, reloc_section,
  949. section_vaddresses, sections,
  950. section_entsize, num_sections,
  951. strtab, ia64jmp_off
  952. + image_target->vaddr_offset,
  953. 2 * ia64jmpnum + got,
  954. image_target);
  955. }
  956. for (i = 0, s = sections;
  957. i < num_sections;
  958. i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
  959. if (SUFFIX (is_data_section) (s, image_target)
  960. || SUFFIX (is_text_section) (s, image_target))
  961. {
  962. if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS)
  963. memset (out_img + section_addresses[i], 0,
  964. grub_host_to_target_addr (s->sh_size));
  965. else
  966. memcpy (out_img + section_addresses[i],
  967. kernel_img + grub_host_to_target_addr (s->sh_offset),
  968. grub_host_to_target_addr (s->sh_size));
  969. }
  970. free (kernel_img);
  971. return out_img;
  972. }
  973. #undef SUFFIX
  974. #undef ELFCLASSXX
  975. #undef Elf_Ehdr
  976. #undef Elf_Phdr
  977. #undef Elf_Shdr
  978. #undef Elf_Addr
  979. #undef Elf_Sym
  980. #undef Elf_Off
  981. #undef Elf_Rela
  982. #undef Elf_Rel
  983. #undef ELF_R_TYPE
  984. #undef ELF_R_SYM
  985. #undef Elf_Word
  986. #undef Elf_Half
  987. #undef Elf_Section
  988. #undef ELF_ST_TYPE