grub-mkimagexx.c 83 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644
  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. #include <config.h>
  20. #include <grub/types.h>
  21. #include <grub/elf.h>
  22. #include <grub/aout.h>
  23. #include <grub/i18n.h>
  24. #include <grub/kernel.h>
  25. #include <grub/disk.h>
  26. #include <grub/emu/misc.h>
  27. #include <grub/util/misc.h>
  28. #include <grub/util/resolve.h>
  29. #include <grub/misc.h>
  30. #include <grub/offsets.h>
  31. #include <grub/crypto.h>
  32. #include <grub/dl.h>
  33. #include <time.h>
  34. #include <multiboot.h>
  35. #include <stdio.h>
  36. #include <unistd.h>
  37. #include <string.h>
  38. #include <stdlib.h>
  39. #include <assert.h>
  40. #include <grub/efi/pe32.h>
  41. #include <grub/uboot/image.h>
  42. #include <grub/arm/reloc.h>
  43. #include <grub/arm64/reloc.h>
  44. #include <grub/ia64/reloc.h>
  45. #include <grub/loongarch64/reloc.h>
  46. #include <grub/osdep/hostfile.h>
  47. #include <grub/util/install.h>
  48. #include <grub/util/mkimage.h>
  49. #include <xen/elfnote.h>
  50. #pragma GCC diagnostic ignored "-Wcast-align"
  51. #define GRUB_MKIMAGEXX
  52. #if !defined(MKIMAGE_ELF32) && !defined(MKIMAGE_ELF64)
  53. #if __SIZEOF_POINTER__ == 8
  54. #include "grub-mkimage64.c"
  55. #else
  56. #include "grub-mkimage32.c"
  57. #endif
  58. #endif
  59. /* These structures are defined according to the CHRP binding to IEEE1275,
  60. "Client Program Format" section. */
  61. struct grub_ieee1275_note_desc
  62. {
  63. grub_uint32_t real_mode;
  64. grub_uint32_t real_base;
  65. grub_uint32_t real_size;
  66. grub_uint32_t virt_base;
  67. grub_uint32_t virt_size;
  68. grub_uint32_t load_base;
  69. };
  70. #define GRUB_IEEE1275_NOTE_NAME "PowerPC"
  71. #define GRUB_IEEE1275_NOTE_TYPE 0x1275
  72. struct grub_ieee1275_note
  73. {
  74. Elf32_Nhdr header;
  75. char name[ALIGN_UP(sizeof (GRUB_IEEE1275_NOTE_NAME), 4)];
  76. struct grub_ieee1275_note_desc descriptor;
  77. };
  78. #define GRUB_XEN_NOTE_NAME "Xen"
  79. struct fixup_block_list
  80. {
  81. struct fixup_block_list *next;
  82. int state;
  83. struct grub_pe32_fixup_block b;
  84. };
  85. #define ALIGN_ADDR(x) (ALIGN_UP((x), image_target->voidp_sizeof))
  86. struct section_metadata
  87. {
  88. Elf_Half num_sections;
  89. Elf_Shdr *sections;
  90. Elf_Addr *addrs;
  91. Elf_Addr *vaddrs;
  92. Elf_Half section_entsize;
  93. Elf_Shdr *symtab;
  94. const char *strtab;
  95. };
  96. #define GRUB_SBAT_NOTE_NAME ".sbat"
  97. #define GRUB_SBAT_NOTE_TYPE 0x53424154 /* "SBAT" */
  98. struct grub_sbat_note {
  99. Elf32_Nhdr header;
  100. char name[ALIGN_UP(sizeof(GRUB_SBAT_NOTE_NAME), 4)];
  101. };
  102. static int
  103. is_relocatable (const struct grub_install_image_target_desc *image_target)
  104. {
  105. return image_target->id == IMAGE_EFI || image_target->id == IMAGE_UBOOT
  106. || (image_target->id == IMAGE_COREBOOT && image_target->elf_target == EM_ARM);
  107. }
  108. #ifdef MKIMAGE_ELF32
  109. /*
  110. * R_ARM_THM_CALL/THM_JUMP24
  111. *
  112. * Relocate Thumb (T32) instruction set relative branches:
  113. * B.W, BL and BLX
  114. */
  115. static grub_err_t
  116. grub_arm_reloc_thm_call (grub_uint16_t *target, Elf32_Addr sym_addr)
  117. {
  118. grub_int32_t offset;
  119. offset = grub_arm_thm_call_get_offset (target);
  120. grub_dprintf ("dl", " sym_addr = 0x%08x", sym_addr);
  121. offset += sym_addr;
  122. grub_dprintf("dl", " BL*: target=%p, sym_addr=0x%08x, offset=%d\n",
  123. target, sym_addr, offset);
  124. /* Keep traditional (pre-Thumb2) limits on blx. In any case if the kernel
  125. is bigger than 2M (currently under 150K) then we probably have a problem
  126. somewhere else. */
  127. if (offset < -0x200000 || offset >= 0x200000)
  128. return grub_error (GRUB_ERR_BAD_MODULE,
  129. "THM_CALL Relocation out of range.");
  130. grub_dprintf ("dl", " relative destination = %p",
  131. (char *) target + offset);
  132. return grub_arm_thm_call_set_offset (target, offset);
  133. }
  134. /*
  135. * R_ARM_THM_JUMP19
  136. *
  137. * Relocate conditional Thumb (T32) B<c>.W
  138. */
  139. static grub_err_t
  140. grub_arm_reloc_thm_jump19 (grub_uint16_t *target, Elf32_Addr sym_addr)
  141. {
  142. grub_int32_t offset;
  143. if (!(sym_addr & 1))
  144. return grub_error (GRUB_ERR_BAD_MODULE,
  145. "Relocation targeting wrong execution state");
  146. offset = grub_arm_thm_jump19_get_offset (target);
  147. /* Adjust and re-truncate offset */
  148. offset += sym_addr;
  149. if (!grub_arm_thm_jump19_check_offset (offset))
  150. return grub_error (GRUB_ERR_BAD_MODULE,
  151. "THM_JUMP19 Relocation out of range.");
  152. grub_arm_thm_jump19_set_offset (target, offset);
  153. return GRUB_ERR_NONE;
  154. }
  155. /*
  156. * R_ARM_JUMP24
  157. *
  158. * Relocate ARM (A32) B
  159. */
  160. static grub_err_t
  161. grub_arm_reloc_jump24 (grub_uint32_t *target, Elf32_Addr sym_addr)
  162. {
  163. grub_int32_t offset;
  164. if (sym_addr & 1)
  165. return grub_error (GRUB_ERR_BAD_MODULE,
  166. "Relocation targeting wrong execution state");
  167. offset = grub_arm_jump24_get_offset (target);
  168. offset += sym_addr;
  169. if (!grub_arm_jump24_check_offset (offset))
  170. return grub_error (GRUB_ERR_BAD_MODULE,
  171. "JUMP24 Relocation out of range.");
  172. grub_arm_jump24_set_offset (target, offset);
  173. return GRUB_ERR_NONE;
  174. }
  175. #endif
  176. void
  177. SUFFIX (grub_mkimage_generate_elf) (const struct grub_install_image_target_desc *image_target,
  178. int note, char *sbat, char **core_img, size_t *core_size,
  179. Elf_Addr target_addr,
  180. struct grub_mkimage_layout *layout)
  181. {
  182. char *elf_img;
  183. size_t program_size;
  184. Elf_Ehdr *ehdr;
  185. Elf_Phdr *phdr;
  186. Elf_Shdr *shdr;
  187. int header_size, footer_size = 0, footer_offset = 0;
  188. int phnum = 1;
  189. int shnum = 4;
  190. int string_size = sizeof (".text") + sizeof ("mods") + 1;
  191. char *footer;
  192. if (sbat)
  193. {
  194. phnum++;
  195. footer_size += ALIGN_UP (sizeof (struct grub_sbat_note) + layout->sbat_size, 4);
  196. }
  197. if (image_target->id != IMAGE_LOONGSON_ELF)
  198. phnum += 2;
  199. if (note)
  200. {
  201. phnum++;
  202. footer_size += sizeof (struct grub_ieee1275_note);
  203. }
  204. if (image_target->id == IMAGE_XEN || image_target->id == IMAGE_XEN_PVH)
  205. {
  206. phnum++;
  207. shnum++;
  208. string_size += sizeof (".xen");
  209. footer_size += (image_target->id == IMAGE_XEN) ? XEN_NOTE_SIZE : XEN_PVH_NOTE_SIZE;
  210. }
  211. header_size = ALIGN_UP (sizeof (*ehdr) + phnum * sizeof (*phdr)
  212. + shnum * sizeof (*shdr) + string_size, layout->align);
  213. program_size = ALIGN_ADDR (*core_size);
  214. elf_img = xmalloc (program_size + header_size + footer_size);
  215. memset (elf_img, 0, program_size + header_size + footer_size);
  216. memcpy (elf_img + header_size, *core_img, *core_size);
  217. ehdr = (void *) elf_img;
  218. phdr = (void *) (elf_img + sizeof (*ehdr));
  219. shdr = (void *) (elf_img + sizeof (*ehdr) + phnum * sizeof (*phdr));
  220. footer = elf_img + program_size + header_size;
  221. memcpy (ehdr->e_ident, ELFMAG, SELFMAG);
  222. ehdr->e_ident[EI_CLASS] = ELFCLASSXX;
  223. if (!image_target->bigendian)
  224. ehdr->e_ident[EI_DATA] = ELFDATA2LSB;
  225. else
  226. ehdr->e_ident[EI_DATA] = ELFDATA2MSB;
  227. ehdr->e_ident[EI_VERSION] = EV_CURRENT;
  228. ehdr->e_ident[EI_OSABI] = ELFOSABI_NONE;
  229. ehdr->e_type = grub_host_to_target16 (ET_EXEC);
  230. ehdr->e_machine = grub_host_to_target16 (image_target->elf_target);
  231. ehdr->e_version = grub_host_to_target32 (EV_CURRENT);
  232. ehdr->e_phoff = grub_host_to_target32 ((char *) phdr - (char *) ehdr);
  233. ehdr->e_phentsize = grub_host_to_target16 (sizeof (*phdr));
  234. ehdr->e_phnum = grub_host_to_target16 (phnum);
  235. ehdr->e_shoff = grub_host_to_target32 ((grub_uint8_t *) shdr
  236. - (grub_uint8_t *) ehdr);
  237. if (image_target->id == IMAGE_LOONGSON_ELF)
  238. ehdr->e_shentsize = grub_host_to_target16 (0);
  239. else
  240. ehdr->e_shentsize = grub_host_to_target16 (sizeof (Elf_Shdr));
  241. ehdr->e_shnum = grub_host_to_target16 (shnum);
  242. ehdr->e_shstrndx = grub_host_to_target16 (1);
  243. ehdr->e_ehsize = grub_host_to_target16 (sizeof (*ehdr));
  244. phdr->p_type = grub_host_to_target32 (PT_LOAD);
  245. phdr->p_offset = grub_host_to_target32 (header_size);
  246. phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X);
  247. ehdr->e_entry = grub_host_to_target32 (target_addr);
  248. phdr->p_vaddr = grub_host_to_target32 (target_addr);
  249. phdr->p_paddr = grub_host_to_target32 (target_addr);
  250. phdr->p_align = grub_host_to_target32 (layout->align > image_target->link_align ?
  251. layout->align : image_target->link_align);
  252. if (image_target->id == IMAGE_LOONGSON_ELF)
  253. ehdr->e_flags = grub_host_to_target32 (0x1000 | EF_MIPS_NOREORDER
  254. | EF_MIPS_PIC | EF_MIPS_CPIC);
  255. else
  256. ehdr->e_flags = 0;
  257. if (image_target->id == IMAGE_LOONGSON_ELF)
  258. {
  259. phdr->p_filesz = grub_host_to_target32 (*core_size);
  260. phdr->p_memsz = grub_host_to_target32 (*core_size);
  261. }
  262. else
  263. {
  264. grub_uint32_t target_addr_mods;
  265. phdr->p_filesz = grub_host_to_target32 (layout->kernel_size);
  266. if (image_target->id == IMAGE_COREBOOT && image_target->elf_target == EM_ARM)
  267. phdr->p_memsz = grub_host_to_target32 (layout->kernel_size);
  268. else
  269. phdr->p_memsz = grub_host_to_target32 (layout->kernel_size + layout->bss_size);
  270. phdr++;
  271. phdr->p_type = grub_host_to_target32 (PT_GNU_STACK);
  272. phdr->p_offset = grub_host_to_target32 (header_size + layout->kernel_size);
  273. phdr->p_paddr = phdr->p_vaddr = phdr->p_filesz = phdr->p_memsz = 0;
  274. phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X);
  275. phdr->p_align = grub_host_to_target32 (image_target->link_align);
  276. phdr++;
  277. phdr->p_type = grub_host_to_target32 (PT_LOAD);
  278. phdr->p_offset = grub_host_to_target32 (header_size + layout->kernel_size);
  279. phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X);
  280. phdr->p_filesz = phdr->p_memsz
  281. = grub_host_to_target32 (*core_size - layout->kernel_size);
  282. if (image_target->id == IMAGE_COREBOOT && image_target->elf_target == EM_386)
  283. target_addr_mods = GRUB_KERNEL_I386_COREBOOT_MODULES_ADDR;
  284. else if (image_target->id == IMAGE_COREBOOT && image_target->elf_target == EM_ARM)
  285. target_addr_mods = ALIGN_UP (target_addr + layout->end
  286. + image_target->mod_gap,
  287. image_target->mod_align);
  288. else
  289. target_addr_mods = ALIGN_UP (target_addr + layout->kernel_size + layout->bss_size
  290. + image_target->mod_gap,
  291. image_target->mod_align);
  292. phdr->p_vaddr = grub_host_to_target_addr (target_addr_mods);
  293. phdr->p_paddr = grub_host_to_target_addr (target_addr_mods);
  294. phdr->p_align = grub_host_to_target32 (image_target->link_align);
  295. }
  296. if (image_target->id == IMAGE_XEN)
  297. {
  298. char *note_start = (elf_img + program_size + header_size);
  299. Elf_Nhdr *note_ptr;
  300. char *ptr = (char *) note_start;
  301. grub_util_info ("adding XEN NOTE segment");
  302. /* Guest OS. */
  303. note_ptr = (Elf_Nhdr *) ptr;
  304. note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
  305. note_ptr->n_descsz = grub_host_to_target32 (sizeof (PACKAGE_NAME));
  306. note_ptr->n_type = grub_host_to_target32 (XEN_ELFNOTE_GUEST_OS);
  307. ptr += sizeof (Elf_Nhdr);
  308. memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
  309. ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
  310. memcpy (ptr, PACKAGE_NAME, sizeof (PACKAGE_NAME));
  311. ptr += ALIGN_UP (sizeof (PACKAGE_NAME), 4);
  312. /* Loader. */
  313. note_ptr = (Elf_Nhdr *) ptr;
  314. note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
  315. note_ptr->n_descsz = grub_host_to_target32 (sizeof ("generic"));
  316. note_ptr->n_type = grub_host_to_target32 (XEN_ELFNOTE_LOADER);
  317. ptr += sizeof (Elf_Nhdr);
  318. memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
  319. ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
  320. memcpy (ptr, "generic", sizeof ("generic"));
  321. ptr += ALIGN_UP (sizeof ("generic"), 4);
  322. /* Version. */
  323. note_ptr = (Elf_Nhdr *) ptr;
  324. note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
  325. note_ptr->n_descsz = grub_host_to_target32 (sizeof ("xen-3.0"));
  326. note_ptr->n_type = grub_host_to_target32 (XEN_ELFNOTE_XEN_VERSION);
  327. ptr += sizeof (Elf_Nhdr);
  328. memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
  329. ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
  330. memcpy (ptr, "xen-3.0", sizeof ("xen-3.0"));
  331. ptr += ALIGN_UP (sizeof ("xen-3.0"), 4);
  332. /* Entry. */
  333. note_ptr = (Elf_Nhdr *) ptr;
  334. note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
  335. note_ptr->n_descsz = grub_host_to_target32 (image_target->voidp_sizeof);
  336. note_ptr->n_type = grub_host_to_target32 (XEN_ELFNOTE_ENTRY);
  337. ptr += sizeof (Elf_Nhdr);
  338. memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
  339. ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
  340. memset (ptr, 0, image_target->voidp_sizeof);
  341. ptr += image_target->voidp_sizeof;
  342. /* Virt base. */
  343. note_ptr = (Elf_Nhdr *) ptr;
  344. note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
  345. note_ptr->n_descsz = grub_host_to_target32 (image_target->voidp_sizeof);
  346. note_ptr->n_type = grub_host_to_target32 (XEN_ELFNOTE_VIRT_BASE);
  347. ptr += sizeof (Elf_Nhdr);
  348. memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
  349. ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
  350. memset (ptr, 0, image_target->voidp_sizeof);
  351. ptr += image_target->voidp_sizeof;
  352. /* PAE. */
  353. if (image_target->elf_target == EM_386)
  354. {
  355. note_ptr = (Elf_Nhdr *) ptr;
  356. note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
  357. note_ptr->n_descsz = grub_host_to_target32 (sizeof ("yes,bimodal"));
  358. note_ptr->n_type = grub_host_to_target32 (XEN_ELFNOTE_PAE_MODE);
  359. ptr += sizeof (Elf_Nhdr);
  360. memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
  361. ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
  362. memcpy (ptr, "yes", sizeof ("yes"));
  363. ptr += ALIGN_UP (sizeof ("yes"), 4);
  364. }
  365. assert (XEN_NOTE_SIZE == (ptr - note_start));
  366. phdr++;
  367. phdr->p_type = grub_host_to_target32 (PT_NOTE);
  368. phdr->p_flags = grub_host_to_target32 (PF_R);
  369. phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof);
  370. phdr->p_vaddr = 0;
  371. phdr->p_paddr = 0;
  372. phdr->p_filesz = grub_host_to_target32 (XEN_NOTE_SIZE);
  373. phdr->p_memsz = 0;
  374. phdr->p_offset = grub_host_to_target32 (header_size + program_size);
  375. footer = ptr;
  376. footer_offset = XEN_NOTE_SIZE;
  377. }
  378. if (image_target->id == IMAGE_XEN_PVH)
  379. {
  380. char *note_start = (elf_img + program_size + header_size);
  381. Elf_Nhdr *note_ptr;
  382. char *ptr = (char *) note_start;
  383. grub_util_info ("adding XEN NOTE segment");
  384. /* Phys32 Entry. */
  385. note_ptr = (Elf_Nhdr *) ptr;
  386. note_ptr->n_namesz = grub_host_to_target32 (sizeof (GRUB_XEN_NOTE_NAME));
  387. note_ptr->n_descsz = grub_host_to_target32 (image_target->voidp_sizeof);
  388. note_ptr->n_type = grub_host_to_target32 (XEN_ELFNOTE_PHYS32_ENTRY);
  389. ptr += sizeof (Elf_Nhdr);
  390. memcpy (ptr, GRUB_XEN_NOTE_NAME, sizeof (GRUB_XEN_NOTE_NAME));
  391. ptr += ALIGN_UP (sizeof (GRUB_XEN_NOTE_NAME), 4);
  392. memset (ptr, 0, image_target->voidp_sizeof);
  393. *(grub_uint32_t *) ptr = GRUB_KERNEL_I386_XEN_PVH_LINK_ADDR;
  394. ptr += image_target->voidp_sizeof;
  395. assert (XEN_PVH_NOTE_SIZE == (ptr - note_start));
  396. phdr++;
  397. phdr->p_type = grub_host_to_target32 (PT_NOTE);
  398. phdr->p_flags = grub_host_to_target32 (PF_R);
  399. phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof);
  400. phdr->p_vaddr = 0;
  401. phdr->p_paddr = 0;
  402. phdr->p_filesz = grub_host_to_target32 (XEN_PVH_NOTE_SIZE);
  403. phdr->p_memsz = 0;
  404. phdr->p_offset = grub_host_to_target32 (header_size + program_size);
  405. footer = ptr;
  406. footer_offset = XEN_PVH_NOTE_SIZE;
  407. }
  408. if (note)
  409. {
  410. int note_size = sizeof (struct grub_ieee1275_note);
  411. struct grub_ieee1275_note *note_ptr = (struct grub_ieee1275_note *)
  412. (elf_img + program_size + header_size);
  413. grub_util_info ("adding CHRP NOTE segment");
  414. note_ptr->header.n_namesz = grub_host_to_target32 (sizeof (GRUB_IEEE1275_NOTE_NAME));
  415. note_ptr->header.n_descsz = grub_host_to_target32 (sizeof (struct grub_ieee1275_note_desc));
  416. note_ptr->header.n_type = grub_host_to_target32 (GRUB_IEEE1275_NOTE_TYPE);
  417. strcpy (note_ptr->name, GRUB_IEEE1275_NOTE_NAME);
  418. note_ptr->descriptor.real_mode = grub_host_to_target32 (0xffffffff);
  419. note_ptr->descriptor.real_base = grub_host_to_target32 (0x00c00000);
  420. note_ptr->descriptor.real_size = grub_host_to_target32 (0xffffffff);
  421. note_ptr->descriptor.virt_base = grub_host_to_target32 (0xffffffff);
  422. note_ptr->descriptor.virt_size = grub_host_to_target32 (0xffffffff);
  423. note_ptr->descriptor.load_base = grub_host_to_target32 (0x00004000);
  424. phdr++;
  425. phdr->p_type = grub_host_to_target32 (PT_NOTE);
  426. phdr->p_flags = grub_host_to_target32 (PF_R);
  427. phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof);
  428. phdr->p_vaddr = 0;
  429. phdr->p_paddr = 0;
  430. phdr->p_filesz = grub_host_to_target32 (note_size);
  431. phdr->p_memsz = 0;
  432. phdr->p_offset = grub_host_to_target32 (header_size + program_size);
  433. footer = (elf_img + program_size + header_size + note_size);
  434. footer_offset += note_size;
  435. }
  436. if (sbat)
  437. {
  438. int note_size = ALIGN_UP (sizeof (struct grub_sbat_note) + layout->sbat_size, 4);
  439. struct grub_sbat_note *note_ptr = (struct grub_sbat_note *) footer;
  440. note_ptr->header.n_namesz = grub_host_to_target32 (sizeof (GRUB_SBAT_NOTE_NAME));
  441. note_ptr->header.n_descsz = grub_host_to_target32 (ALIGN_UP(layout->sbat_size, 4));
  442. note_ptr->header.n_type = grub_host_to_target32 (GRUB_SBAT_NOTE_TYPE);
  443. memcpy (note_ptr->name, GRUB_SBAT_NOTE_NAME, sizeof (GRUB_SBAT_NOTE_NAME));
  444. memcpy ((char *)(note_ptr + 1), sbat, layout->sbat_size);
  445. phdr++;
  446. phdr->p_type = grub_host_to_target32 (PT_NOTE);
  447. phdr->p_flags = grub_host_to_target32 (PF_R);
  448. phdr->p_align = grub_host_to_target32 (image_target->voidp_sizeof);
  449. phdr->p_vaddr = 0;
  450. phdr->p_paddr = 0;
  451. phdr->p_filesz = grub_host_to_target32 (note_size);
  452. phdr->p_memsz = 0;
  453. phdr->p_offset = grub_host_to_target32 (header_size + program_size + footer_offset);
  454. }
  455. {
  456. char *str_start = (elf_img + sizeof (*ehdr) + phnum * sizeof (*phdr)
  457. + shnum * sizeof (*shdr));
  458. char *ptr = str_start + 1;
  459. shdr++;
  460. shdr->sh_name = grub_host_to_target32 (0);
  461. shdr->sh_type = grub_host_to_target32 (SHT_STRTAB);
  462. shdr->sh_addr = grub_host_to_target_addr (0);
  463. shdr->sh_offset = grub_host_to_target_addr (str_start - elf_img);
  464. shdr->sh_size = grub_host_to_target32 (string_size);
  465. shdr->sh_link = grub_host_to_target32 (0);
  466. shdr->sh_info = grub_host_to_target32 (0);
  467. shdr->sh_addralign = grub_host_to_target32 (layout->align);
  468. shdr->sh_entsize = grub_host_to_target32 (0);
  469. shdr++;
  470. memcpy (ptr, ".text", sizeof (".text"));
  471. shdr->sh_name = grub_host_to_target32 (ptr - str_start);
  472. ptr += sizeof (".text");
  473. shdr->sh_type = grub_host_to_target32 (SHT_PROGBITS);
  474. shdr->sh_addr = grub_host_to_target_addr (target_addr);
  475. shdr->sh_offset = grub_host_to_target_addr (header_size);
  476. shdr->sh_size = grub_host_to_target32 (layout->kernel_size);
  477. shdr->sh_link = grub_host_to_target32 (0);
  478. shdr->sh_info = grub_host_to_target32 (0);
  479. shdr->sh_addralign = grub_host_to_target32 (layout->align);
  480. shdr->sh_entsize = grub_host_to_target32 (0);
  481. shdr++;
  482. memcpy (ptr, "mods", sizeof ("mods"));
  483. shdr->sh_name = grub_host_to_target32 (ptr - str_start);
  484. ptr += sizeof ("mods");
  485. shdr->sh_type = grub_host_to_target32 (SHT_PROGBITS);
  486. shdr->sh_addr = grub_host_to_target_addr (target_addr + layout->kernel_size);
  487. shdr->sh_offset = grub_host_to_target_addr (header_size + layout->kernel_size);
  488. shdr->sh_size = grub_host_to_target32 (*core_size - layout->kernel_size);
  489. shdr->sh_link = grub_host_to_target32 (0);
  490. shdr->sh_info = grub_host_to_target32 (0);
  491. shdr->sh_addralign = grub_host_to_target32 (image_target->voidp_sizeof);
  492. shdr->sh_entsize = grub_host_to_target32 (0);
  493. shdr++;
  494. if (image_target->id == IMAGE_XEN || image_target->id == IMAGE_XEN_PVH)
  495. {
  496. memcpy (ptr, ".xen", sizeof (".xen"));
  497. shdr->sh_name = grub_host_to_target32 (ptr - str_start);
  498. ptr += sizeof (".xen");
  499. shdr->sh_type = grub_host_to_target32 (SHT_PROGBITS);
  500. shdr->sh_addr = grub_host_to_target_addr (target_addr + layout->kernel_size);
  501. shdr->sh_offset = grub_host_to_target_addr (program_size + header_size);
  502. if (image_target->id == IMAGE_XEN)
  503. shdr->sh_size = grub_host_to_target32 (XEN_NOTE_SIZE);
  504. else
  505. shdr->sh_size = grub_host_to_target32 (XEN_PVH_NOTE_SIZE);
  506. shdr->sh_link = grub_host_to_target32 (0);
  507. shdr->sh_info = grub_host_to_target32 (0);
  508. shdr->sh_addralign = grub_host_to_target32 (image_target->voidp_sizeof);
  509. shdr->sh_entsize = grub_host_to_target32 (0);
  510. shdr++;
  511. }
  512. }
  513. free (*core_img);
  514. *core_img = elf_img;
  515. *core_size = program_size + header_size + footer_size;
  516. }
  517. /* Relocate symbols; note that this function overwrites the symbol table.
  518. Return the address of a start symbol. */
  519. static Elf_Addr
  520. SUFFIX (relocate_symbols) (Elf_Ehdr *e, struct section_metadata *smd,
  521. void *jumpers, Elf_Addr jumpers_addr,
  522. Elf_Addr bss_start, Elf_Addr end,
  523. const struct grub_install_image_target_desc *image_target)
  524. {
  525. Elf_Word symtab_size, sym_size, num_syms;
  526. Elf_Off symtab_offset;
  527. Elf_Addr start_address = (Elf_Addr) -1;
  528. Elf_Sym *sym;
  529. Elf_Word i;
  530. Elf_Shdr *symtab_section;
  531. const char *symtab;
  532. grub_uint64_t *jptr = jumpers;
  533. symtab_section = (Elf_Shdr *) ((char *) smd->sections
  534. + grub_target_to_host32 (smd->symtab->sh_link)
  535. * smd->section_entsize);
  536. symtab = (char *) e + grub_target_to_host (symtab_section->sh_offset);
  537. symtab_size = grub_target_to_host (smd->symtab->sh_size);
  538. sym_size = grub_target_to_host (smd->symtab->sh_entsize);
  539. symtab_offset = grub_target_to_host (smd->symtab->sh_offset);
  540. num_syms = symtab_size / sym_size;
  541. for (i = 0, sym = (Elf_Sym *) ((char *) e + symtab_offset);
  542. i < num_syms;
  543. i++, sym = (Elf_Sym *) ((char *) sym + sym_size))
  544. {
  545. Elf_Section cur_index;
  546. const char *name;
  547. name = symtab + grub_target_to_host32 (sym->st_name);
  548. cur_index = grub_target_to_host16 (sym->st_shndx);
  549. if (cur_index == STN_ABS)
  550. {
  551. continue;
  552. }
  553. else if (cur_index == STN_UNDEF)
  554. {
  555. if (sym->st_name && grub_strcmp (name, "__bss_start") == 0)
  556. sym->st_value = bss_start;
  557. else if (sym->st_name && grub_strcmp (name, "_end") == 0)
  558. sym->st_value = end;
  559. else if (sym->st_name)
  560. grub_util_error ("undefined symbol %s", name);
  561. else
  562. continue;
  563. }
  564. else if (cur_index >= smd->num_sections)
  565. grub_util_error ("section %d does not exist", cur_index);
  566. else
  567. {
  568. sym->st_value = (grub_target_to_host (sym->st_value)
  569. + smd->vaddrs[cur_index]);
  570. }
  571. if (image_target->elf_target == EM_IA_64 && ELF_ST_TYPE (sym->st_info)
  572. == STT_FUNC)
  573. {
  574. *jptr = grub_host_to_target64 (sym->st_value);
  575. sym->st_value = (char *) jptr - (char *) jumpers + jumpers_addr;
  576. jptr++;
  577. *jptr = 0;
  578. jptr++;
  579. }
  580. grub_util_info ("locating %s at 0x%" GRUB_HOST_PRIxLONG_LONG
  581. " (0x%" GRUB_HOST_PRIxLONG_LONG ")", name,
  582. (unsigned long long) sym->st_value,
  583. (unsigned long long) smd->vaddrs[cur_index]);
  584. if (start_address == (Elf_Addr)-1)
  585. if (strcmp (name, "_start") == 0 || strcmp (name, "start") == 0)
  586. start_address = sym->st_value;
  587. }
  588. return start_address;
  589. }
  590. /* Return the address of a symbol at the index I in the section S. */
  591. static Elf_Addr
  592. SUFFIX (get_symbol_address) (Elf_Ehdr *e, Elf_Shdr *s, Elf_Word i,
  593. const struct grub_install_image_target_desc *image_target)
  594. {
  595. Elf_Sym *sym;
  596. sym = (Elf_Sym *) ((char *) e
  597. + grub_target_to_host (s->sh_offset)
  598. + i * grub_target_to_host (s->sh_entsize));
  599. return sym->st_value;
  600. }
  601. /* Return the address of a modified value. */
  602. static Elf_Addr *
  603. SUFFIX (get_target_address) (Elf_Ehdr *e, Elf_Shdr *s, Elf_Addr offset,
  604. const struct grub_install_image_target_desc *image_target)
  605. {
  606. return (Elf_Addr *) ((char *) e + grub_target_to_host (s->sh_offset) + offset);
  607. }
  608. #ifdef MKIMAGE_ELF64
  609. static Elf_Addr
  610. SUFFIX (count_funcs) (Elf_Ehdr *e, Elf_Shdr *symtab_section,
  611. const struct grub_install_image_target_desc *image_target)
  612. {
  613. Elf_Word symtab_size, sym_size, num_syms;
  614. Elf_Off symtab_offset;
  615. Elf_Sym *sym;
  616. Elf_Word i;
  617. int ret = 0;
  618. symtab_size = grub_target_to_host (symtab_section->sh_size);
  619. sym_size = grub_target_to_host (symtab_section->sh_entsize);
  620. symtab_offset = grub_target_to_host (symtab_section->sh_offset);
  621. num_syms = symtab_size / sym_size;
  622. for (i = 0, sym = (Elf_Sym *) ((char *) e + symtab_offset);
  623. i < num_syms;
  624. i++, sym = (Elf_Sym *) ((char *) sym + sym_size))
  625. if (ELF_ST_TYPE (sym->st_info) == STT_FUNC)
  626. ret++;
  627. return ret;
  628. }
  629. #endif
  630. #ifdef MKIMAGE_ELF32
  631. /* Deal with relocation information. This function relocates addresses
  632. within the virtual address space starting from 0. So only relative
  633. addresses can be fully resolved. Absolute addresses must be relocated
  634. again by a PE32 relocator when loaded. */
  635. static grub_size_t
  636. arm_get_trampoline_size (Elf_Ehdr *e,
  637. Elf_Shdr *sections,
  638. Elf_Half section_entsize,
  639. Elf_Half num_sections,
  640. const struct grub_install_image_target_desc *image_target)
  641. {
  642. Elf_Half i;
  643. Elf_Shdr *s;
  644. grub_size_t ret = 0;
  645. for (i = 0, s = sections;
  646. i < num_sections;
  647. i++, s = (Elf_Shdr *) ((char *) s + section_entsize))
  648. if ((s->sh_type == grub_host_to_target32 (SHT_REL)) ||
  649. (s->sh_type == grub_host_to_target32 (SHT_RELA)))
  650. {
  651. Elf_Rela *r;
  652. Elf_Word rtab_size, r_size, num_rs;
  653. Elf_Off rtab_offset;
  654. Elf_Shdr *symtab_section;
  655. Elf_Word j;
  656. symtab_section = (Elf_Shdr *) ((char *) sections
  657. + (grub_target_to_host32 (s->sh_link)
  658. * section_entsize));
  659. rtab_size = grub_target_to_host (s->sh_size);
  660. r_size = grub_target_to_host (s->sh_entsize);
  661. rtab_offset = grub_target_to_host (s->sh_offset);
  662. num_rs = rtab_size / r_size;
  663. for (j = 0, r = (Elf_Rela *) ((char *) e + rtab_offset);
  664. j < num_rs;
  665. j++, r = (Elf_Rela *) ((char *) r + r_size))
  666. {
  667. Elf_Addr info;
  668. Elf_Addr sym_addr;
  669. info = grub_target_to_host (r->r_info);
  670. sym_addr = SUFFIX (get_symbol_address) (e, symtab_section,
  671. ELF_R_SYM (info), image_target);
  672. sym_addr += (s->sh_type == grub_target_to_host32 (SHT_RELA)) ?
  673. grub_target_to_host (r->r_addend) : 0;
  674. switch (ELF_R_TYPE (info))
  675. {
  676. case R_ARM_ABS32:
  677. case R_ARM_V4BX:
  678. break;
  679. case R_ARM_THM_CALL:
  680. case R_ARM_THM_JUMP24:
  681. case R_ARM_THM_JUMP19:
  682. if (!(sym_addr & 1))
  683. ret += 8;
  684. break;
  685. case R_ARM_CALL:
  686. case R_ARM_JUMP24:
  687. if (sym_addr & 1)
  688. ret += 16;
  689. break;
  690. default:
  691. grub_util_error (_("relocation 0x%x is not implemented yet"),
  692. (unsigned int) ELF_R_TYPE (info));
  693. break;
  694. }
  695. }
  696. }
  697. return ret;
  698. }
  699. #endif
  700. static int
  701. SUFFIX (is_kept_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target);
  702. static int
  703. SUFFIX (is_kept_reloc_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target,
  704. struct section_metadata *smd);
  705. /* Deal with relocation information. This function relocates addresses
  706. within the virtual address space starting from 0. So only relative
  707. addresses can be fully resolved. Absolute addresses must be relocated
  708. again by a PE32 relocator when loaded. */
  709. static void
  710. SUFFIX (relocate_addrs) (Elf_Ehdr *e, struct section_metadata *smd,
  711. char *pe_target, Elf_Addr tramp_off, Elf_Addr got_off,
  712. const struct grub_install_image_target_desc *image_target)
  713. {
  714. Elf_Half i;
  715. Elf_Shdr *s;
  716. #ifdef MKIMAGE_ELF64
  717. struct grub_ia64_trampoline *tr = (void *) (pe_target + tramp_off);
  718. grub_uint64_t *gpptr = (void *) (pe_target + got_off);
  719. unsigned unmatched_adr_got_page = 0;
  720. struct grub_loongarch64_stack stack;
  721. grub_loongarch64_stack_init (&stack);
  722. #define MASK19 ((1 << 19) - 1)
  723. #else
  724. grub_uint32_t *tr = (void *) (pe_target + tramp_off);
  725. #endif
  726. for (i = 0, s = smd->sections;
  727. i < smd->num_sections;
  728. i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
  729. if ((s->sh_type == grub_host_to_target32 (SHT_REL)) ||
  730. (s->sh_type == grub_host_to_target32 (SHT_RELA)))
  731. {
  732. Elf_Rela *r;
  733. Elf_Word rtab_size, r_size, num_rs;
  734. Elf_Off rtab_offset;
  735. Elf_Word target_section_index;
  736. Elf_Addr target_section_addr;
  737. Elf_Shdr *target_section;
  738. Elf_Word j;
  739. if (!SUFFIX (is_kept_section) (s, image_target) &&
  740. !SUFFIX (is_kept_reloc_section) (s, image_target, smd))
  741. {
  742. grub_util_info ("not translating relocations for omitted section %s",
  743. smd->strtab + grub_le_to_cpu32 (s->sh_name));
  744. continue;
  745. }
  746. target_section_index = grub_target_to_host32 (s->sh_info);
  747. target_section_addr = smd->addrs[target_section_index];
  748. target_section = (Elf_Shdr *) ((char *) smd->sections
  749. + (target_section_index
  750. * smd->section_entsize));
  751. grub_util_info ("dealing with the relocation section %s for %s",
  752. smd->strtab + grub_target_to_host32 (s->sh_name),
  753. smd->strtab + grub_target_to_host32 (target_section->sh_name));
  754. rtab_size = grub_target_to_host (s->sh_size);
  755. r_size = grub_target_to_host (s->sh_entsize);
  756. rtab_offset = grub_target_to_host (s->sh_offset);
  757. num_rs = rtab_size / r_size;
  758. for (j = 0, r = (Elf_Rela *) ((char *) e + rtab_offset);
  759. j < num_rs;
  760. j++, r = (Elf_Rela *) ((char *) r + r_size))
  761. {
  762. Elf_Addr info;
  763. Elf_Addr offset;
  764. Elf_Addr sym_addr;
  765. Elf_Addr *target;
  766. Elf_Addr addend;
  767. offset = grub_target_to_host (r->r_offset);
  768. target = SUFFIX (get_target_address) (e, target_section,
  769. offset, image_target);
  770. info = grub_target_to_host (r->r_info);
  771. sym_addr = SUFFIX (get_symbol_address) (e, smd->symtab,
  772. ELF_R_SYM (info), image_target);
  773. addend = (s->sh_type == grub_target_to_host32 (SHT_RELA)) ?
  774. grub_target_to_host (r->r_addend) : 0;
  775. switch (image_target->elf_target)
  776. {
  777. case EM_386:
  778. switch (ELF_R_TYPE (info))
  779. {
  780. case R_386_NONE:
  781. break;
  782. case R_386_32:
  783. /* This is absolute. */
  784. *target = grub_host_to_target32 (grub_target_to_host32 (*target)
  785. + addend + sym_addr);
  786. grub_util_info ("relocating an R_386_32 entry to 0x%"
  787. GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
  788. GRUB_HOST_PRIxLONG_LONG,
  789. (unsigned long long) *target,
  790. (unsigned long long) offset);
  791. break;
  792. case R_386_PC32:
  793. /* This is relative. */
  794. *target = grub_host_to_target32 (grub_target_to_host32 (*target)
  795. + addend + sym_addr
  796. - target_section_addr - offset
  797. - image_target->vaddr_offset);
  798. grub_util_info ("relocating an R_386_PC32 entry to 0x%"
  799. GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
  800. GRUB_HOST_PRIxLONG_LONG,
  801. (unsigned long long) *target,
  802. (unsigned long long) offset);
  803. break;
  804. default:
  805. grub_util_error (_("relocation 0x%x is not implemented yet"),
  806. (unsigned int) ELF_R_TYPE (info));
  807. break;
  808. }
  809. break;
  810. #ifdef MKIMAGE_ELF64
  811. case EM_X86_64:
  812. switch (ELF_R_TYPE (info))
  813. {
  814. case R_X86_64_NONE:
  815. break;
  816. case R_X86_64_64:
  817. *target = grub_host_to_target64 (grub_target_to_host64 (*target)
  818. + addend + sym_addr);
  819. grub_util_info ("relocating an R_X86_64_64 entry to 0x%"
  820. GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
  821. GRUB_HOST_PRIxLONG_LONG,
  822. (unsigned long long) *target,
  823. (unsigned long long) offset);
  824. break;
  825. case R_X86_64_PC32:
  826. case R_X86_64_PLT32:
  827. {
  828. grub_uint32_t *t32 = (grub_uint32_t *) target;
  829. *t32 = grub_host_to_target64 (grub_target_to_host32 (*t32)
  830. + addend + sym_addr
  831. - target_section_addr - offset
  832. - image_target->vaddr_offset);
  833. grub_util_info ("relocating an R_X86_64_PC32 entry to 0x%x at the offset 0x%"
  834. GRUB_HOST_PRIxLONG_LONG,
  835. *t32, (unsigned long long) offset);
  836. break;
  837. }
  838. case R_X86_64_PC64:
  839. {
  840. *target = grub_host_to_target64 (grub_target_to_host64 (*target)
  841. + addend + sym_addr
  842. - target_section_addr - offset
  843. - image_target->vaddr_offset);
  844. grub_util_info ("relocating an R_X86_64_PC64 entry to 0x%"
  845. GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
  846. GRUB_HOST_PRIxLONG_LONG,
  847. (unsigned long long) *target,
  848. (unsigned long long) offset);
  849. break;
  850. }
  851. case R_X86_64_32:
  852. case R_X86_64_32S:
  853. {
  854. grub_uint32_t *t32 = (grub_uint32_t *) target;
  855. *t32 = grub_host_to_target64 (grub_target_to_host32 (*t32)
  856. + addend + sym_addr);
  857. grub_util_info ("relocating an R_X86_64_32(S) entry to 0x%x at the offset 0x%"
  858. GRUB_HOST_PRIxLONG_LONG,
  859. *t32, (unsigned long long) offset);
  860. break;
  861. }
  862. default:
  863. grub_util_error (_("relocation 0x%x is not implemented yet"),
  864. (unsigned int) ELF_R_TYPE (info));
  865. break;
  866. }
  867. break;
  868. case EM_IA_64:
  869. switch (ELF_R_TYPE (info))
  870. {
  871. case R_IA64_PCREL21B:
  872. {
  873. grub_uint64_t noff;
  874. grub_ia64_make_trampoline (tr, addend + sym_addr);
  875. noff = ((char *) tr - (char *) pe_target
  876. - target_section_addr - (offset & ~3)) >> 4;
  877. tr++;
  878. if (noff & ~MASK19)
  879. grub_util_error ("trampoline offset too big (%"
  880. GRUB_HOST_PRIxLONG_LONG ")",
  881. (unsigned long long) noff);
  882. grub_ia64_add_value_to_slot_20b ((grub_addr_t) target, noff);
  883. }
  884. break;
  885. case R_IA64_LTOFF22X:
  886. case R_IA64_LTOFF22:
  887. {
  888. Elf_Sym *sym;
  889. sym = (Elf_Sym *) ((char *) e
  890. + grub_target_to_host (smd->symtab->sh_offset)
  891. + ELF_R_SYM (info) * grub_target_to_host (smd->symtab->sh_entsize));
  892. if (ELF_ST_TYPE (sym->st_info) == STT_FUNC)
  893. sym_addr = grub_target_to_host64 (*(grub_uint64_t *) (pe_target
  894. + sym->st_value
  895. - image_target->vaddr_offset));
  896. }
  897. /* FALLTHROUGH */
  898. case R_IA64_LTOFF_FPTR22:
  899. *gpptr = grub_host_to_target64 (addend + sym_addr);
  900. grub_ia64_add_value_to_slot_21 ((grub_addr_t) target,
  901. (char *) gpptr - (char *) pe_target
  902. + image_target->vaddr_offset);
  903. gpptr++;
  904. break;
  905. case R_IA64_GPREL22:
  906. grub_ia64_add_value_to_slot_21 ((grub_addr_t) target,
  907. addend + sym_addr);
  908. break;
  909. case R_IA64_GPREL64I:
  910. grub_ia64_set_immu64 ((grub_addr_t) target,
  911. addend + sym_addr);
  912. break;
  913. case R_IA64_PCREL64LSB:
  914. *target = grub_host_to_target64 (grub_target_to_host64 (*target)
  915. + addend + sym_addr
  916. - target_section_addr - offset
  917. - image_target->vaddr_offset);
  918. break;
  919. case R_IA64_SEGREL64LSB:
  920. *target = grub_host_to_target64 (grub_target_to_host64 (*target)
  921. + addend + sym_addr - target_section_addr);
  922. break;
  923. case R_IA64_DIR64LSB:
  924. case R_IA64_FPTR64LSB:
  925. *target = grub_host_to_target64 (grub_target_to_host64 (*target)
  926. + addend + sym_addr);
  927. grub_util_info ("relocating a direct entry to 0x%"
  928. GRUB_HOST_PRIxLONG_LONG " at the offset 0x%"
  929. GRUB_HOST_PRIxLONG_LONG,
  930. (unsigned long long)
  931. grub_target_to_host64 (*target),
  932. (unsigned long long) offset);
  933. break;
  934. /* We treat LTOFF22X as LTOFF22, so we can ignore LDXMOV. */
  935. case R_IA64_LDXMOV:
  936. break;
  937. default:
  938. grub_util_error (_("relocation 0x%x is not implemented yet"),
  939. (unsigned int) ELF_R_TYPE (info));
  940. break;
  941. }
  942. break;
  943. case EM_AARCH64:
  944. {
  945. sym_addr += addend;
  946. switch (ELF_R_TYPE (info))
  947. {
  948. case R_AARCH64_ABS64:
  949. {
  950. *target = grub_host_to_target64 (grub_target_to_host64 (*target) + sym_addr);
  951. }
  952. break;
  953. case R_AARCH64_PREL32:
  954. {
  955. grub_uint32_t *t32 = (grub_uint32_t *) target;
  956. *t32 = grub_host_to_target64 (grub_target_to_host32 (*t32)
  957. + sym_addr
  958. - target_section_addr - offset
  959. - image_target->vaddr_offset);
  960. grub_util_info ("relocating an R_AARCH64_PREL32 entry to 0x%x at the offset 0x%"
  961. GRUB_HOST_PRIxLONG_LONG,
  962. *t32, (unsigned long long) offset);
  963. break;
  964. }
  965. case R_AARCH64_ADD_ABS_LO12_NC:
  966. grub_arm64_set_abs_lo12 ((grub_uint32_t *) target,
  967. sym_addr);
  968. break;
  969. case R_AARCH64_LDST64_ABS_LO12_NC:
  970. grub_arm64_set_abs_lo12_ldst64 ((grub_uint32_t *) target,
  971. sym_addr);
  972. break;
  973. case R_AARCH64_JUMP26:
  974. case R_AARCH64_CALL26:
  975. {
  976. sym_addr -= offset;
  977. sym_addr -= target_section_addr + image_target->vaddr_offset;
  978. if (!grub_arm_64_check_xxxx26_offset (sym_addr))
  979. grub_util_error ("%s", "CALL26 Relocation out of range");
  980. grub_arm64_set_xxxx26_offset((grub_uint32_t *)target,
  981. sym_addr);
  982. }
  983. break;
  984. case R_AARCH64_ADR_GOT_PAGE:
  985. {
  986. Elf64_Rela *rel2;
  987. grub_int64_t gpoffset = (((char *) gpptr - (char *) pe_target + image_target->vaddr_offset) & ~0xfffULL)
  988. - ((offset + target_section_addr + image_target->vaddr_offset) & ~0xfffULL);
  989. unsigned k;
  990. *gpptr = grub_host_to_target64 (sym_addr);
  991. unmatched_adr_got_page++;
  992. if (!grub_arm64_check_hi21_signed (gpoffset))
  993. grub_util_error ("HI21 out of range");
  994. grub_arm64_set_hi21((grub_uint32_t *)target,
  995. gpoffset);
  996. for (k = 0, rel2 = (Elf_Rela *) ((char *) r + r_size);
  997. k < num_rs;
  998. k++, rel2 = (Elf_Rela *) ((char *) rel2 + r_size))
  999. if (ELF_R_SYM (rel2->r_info)
  1000. == ELF_R_SYM (r->r_info)
  1001. && r->r_addend == rel2->r_addend
  1002. && ELF_R_TYPE (rel2->r_info) == R_AARCH64_LD64_GOT_LO12_NC)
  1003. {
  1004. grub_arm64_set_abs_lo12_ldst64 ((grub_uint32_t *) SUFFIX (get_target_address) (e, target_section,
  1005. grub_target_to_host (rel2->r_offset), image_target),
  1006. ((char *) gpptr - (char *) pe_target + image_target->vaddr_offset));
  1007. break;
  1008. }
  1009. if (k >= num_rs)
  1010. grub_util_error ("ADR_GOT_PAGE without matching LD64_GOT_LO12_NC");
  1011. gpptr++;
  1012. }
  1013. break;
  1014. case R_AARCH64_LD64_GOT_LO12_NC:
  1015. if (unmatched_adr_got_page == 0)
  1016. grub_util_error ("LD64_GOT_LO12_NC without matching ADR_GOT_PAGE");
  1017. unmatched_adr_got_page--;
  1018. break;
  1019. case R_AARCH64_ADR_PREL_PG_HI21:
  1020. {
  1021. sym_addr &= ~0xfffULL;
  1022. sym_addr -= (offset + target_section_addr + image_target->vaddr_offset) & ~0xfffULL;
  1023. if (!grub_arm64_check_hi21_signed (sym_addr))
  1024. grub_util_error ("%s", "CALL26 Relocation out of range");
  1025. grub_arm64_set_hi21((grub_uint32_t *)target,
  1026. sym_addr);
  1027. }
  1028. break;
  1029. default:
  1030. grub_util_error (_("relocation 0x%x is not implemented yet"),
  1031. (unsigned int) ELF_R_TYPE (info));
  1032. break;
  1033. }
  1034. break;
  1035. }
  1036. case EM_LOONGARCH:
  1037. {
  1038. grub_int64_t pc;
  1039. grub_uint32_t *t32 = (grub_uint32_t *) target;
  1040. sym_addr += addend;
  1041. pc = offset + target_section_addr + image_target->vaddr_offset;
  1042. switch (ELF_R_TYPE (info))
  1043. {
  1044. case R_LARCH_64:
  1045. {
  1046. grub_uint64_t *t64 = (grub_uint64_t *) target;
  1047. *t64 = grub_host_to_target64 (grub_target_to_host64 (*t64) + sym_addr);
  1048. }
  1049. break;
  1050. case R_LARCH_MARK_LA:
  1051. break;
  1052. case R_LARCH_SOP_PUSH_PCREL:
  1053. case R_LARCH_SOP_PUSH_PLT_PCREL:
  1054. grub_loongarch64_sop_push (&stack, sym_addr
  1055. -(target_section_addr
  1056. +offset
  1057. +image_target->vaddr_offset));
  1058. break;
  1059. case R_LARCH_B26:
  1060. {
  1061. grub_int64_t off;
  1062. off = sym_addr - pc;
  1063. grub_loongarch64_b26 (t32, off);
  1064. }
  1065. break;
  1066. case R_LARCH_ABS_HI20:
  1067. grub_loongarch64_xxx_hi20 (t32, sym_addr);
  1068. break;
  1069. case R_LARCH_ABS64_LO20:
  1070. grub_loongarch64_abs64_lo20 (t32, sym_addr);
  1071. break;
  1072. case R_LARCH_ABS64_HI12:
  1073. grub_loongarch64_abs64_hi12 (t32, sym_addr);
  1074. break;
  1075. case R_LARCH_PCALA_HI20:
  1076. {
  1077. grub_int32_t hi20;
  1078. hi20 = (((sym_addr + 0x800) & ~0xfffULL) - (pc & ~0xfffULL));
  1079. grub_loongarch64_xxx_hi20 (t32, hi20);
  1080. }
  1081. break;
  1082. case R_LARCH_ABS_LO12:
  1083. case R_LARCH_PCALA_LO12:
  1084. grub_loongarch64_xxx_lo12 (t32, sym_addr);
  1085. break;
  1086. GRUB_LOONGARCH64_RELOCATION (&stack, target, sym_addr)
  1087. default:
  1088. grub_util_error (_("relocation 0x%x is not implemented yet"),
  1089. (unsigned int) ELF_R_TYPE (info));
  1090. break;
  1091. }
  1092. break;
  1093. }
  1094. #endif
  1095. #if defined(MKIMAGE_ELF32)
  1096. case EM_ARM:
  1097. {
  1098. sym_addr += addend;
  1099. sym_addr -= image_target->vaddr_offset;
  1100. switch (ELF_R_TYPE (info))
  1101. {
  1102. case R_ARM_ABS32:
  1103. {
  1104. grub_util_info (" ABS32:\toffset=%d\t(0x%08x)",
  1105. (int) sym_addr, (int) sym_addr);
  1106. /* Data will be naturally aligned */
  1107. if (image_target->id == IMAGE_EFI)
  1108. sym_addr += GRUB_PE32_SECTION_ALIGNMENT;
  1109. *target = grub_host_to_target32 (grub_target_to_host32 (*target) + sym_addr);
  1110. }
  1111. break;
  1112. /* Happens when compiled with -march=armv4.
  1113. Since currently we need at least armv5, keep bx as-is.
  1114. */
  1115. case R_ARM_V4BX:
  1116. break;
  1117. case R_ARM_THM_CALL:
  1118. case R_ARM_THM_JUMP24:
  1119. case R_ARM_THM_JUMP19:
  1120. {
  1121. grub_err_t err;
  1122. Elf_Sym *sym;
  1123. grub_util_info (" THM_JUMP24:\ttarget=0x%08lx\toffset=(0x%08x)",
  1124. (unsigned long) ((char *) target
  1125. - (char *) e),
  1126. sym_addr);
  1127. sym = (Elf_Sym *) ((char *) e
  1128. + grub_target_to_host (smd->symtab->sh_offset)
  1129. + ELF_R_SYM (info) * grub_target_to_host (smd->symtab->sh_entsize));
  1130. if (ELF_ST_TYPE (sym->st_info) != STT_FUNC)
  1131. sym_addr |= 1;
  1132. if (!(sym_addr & 1))
  1133. {
  1134. grub_uint32_t tr_addr;
  1135. grub_int32_t new_offset;
  1136. tr_addr = (char *) tr - (char *) pe_target
  1137. - target_section_addr;
  1138. new_offset = sym_addr - tr_addr - 12;
  1139. if (!grub_arm_jump24_check_offset (new_offset))
  1140. return grub_util_error ("jump24 relocation out of range");
  1141. tr[0] = grub_host_to_target32 (0x46c04778); /* bx pc; nop */
  1142. tr[1] = grub_host_to_target32 (((new_offset >> 2) & 0xffffff) | 0xea000000); /* b new_offset */
  1143. tr += 2;
  1144. sym_addr = tr_addr | 1;
  1145. }
  1146. sym_addr -= offset;
  1147. /* Thumb instructions can be 16-bit aligned */
  1148. if (ELF_R_TYPE (info) == R_ARM_THM_JUMP19)
  1149. err = grub_arm_reloc_thm_jump19 ((grub_uint16_t *) target, sym_addr);
  1150. else
  1151. err = grub_arm_reloc_thm_call ((grub_uint16_t *) target,
  1152. sym_addr);
  1153. if (err)
  1154. grub_util_error ("%s", grub_errmsg);
  1155. }
  1156. break;
  1157. case R_ARM_CALL:
  1158. case R_ARM_JUMP24:
  1159. {
  1160. grub_err_t err;
  1161. grub_util_info (" JUMP24:\ttarget=0x%08lx\toffset=(0x%08x)", (unsigned long) ((char *) target - (char *) e), sym_addr);
  1162. if (sym_addr & 1)
  1163. {
  1164. grub_uint32_t tr_addr;
  1165. grub_int32_t new_offset;
  1166. tr_addr = (char *) tr - (char *) pe_target
  1167. - target_section_addr;
  1168. new_offset = sym_addr - tr_addr - 12;
  1169. /* There is no immediate version of bx, only register one... */
  1170. tr[0] = grub_host_to_target32 (0xe59fc004); /* ldr ip, [pc, #4] */
  1171. tr[1] = grub_host_to_target32 (0xe08cc00f); /* add ip, ip, pc */
  1172. tr[2] = grub_host_to_target32 (0xe12fff1c); /* bx ip */
  1173. tr[3] = grub_host_to_target32 (new_offset | 1);
  1174. tr += 4;
  1175. sym_addr = tr_addr;
  1176. }
  1177. sym_addr -= offset;
  1178. err = grub_arm_reloc_jump24 (target,
  1179. sym_addr);
  1180. if (err)
  1181. grub_util_error ("%s", grub_errmsg);
  1182. }
  1183. break;
  1184. default:
  1185. grub_util_error (_("relocation 0x%x is not implemented yet"),
  1186. (unsigned int) ELF_R_TYPE (info));
  1187. break;
  1188. }
  1189. break;
  1190. }
  1191. #endif /* MKIMAGE_ELF32 */
  1192. case EM_RISCV:
  1193. {
  1194. grub_uint64_t *t64 = (grub_uint64_t *) target;
  1195. grub_uint32_t *t32 = (grub_uint32_t *) target;
  1196. grub_uint16_t *t16 = (grub_uint16_t *) target;
  1197. grub_uint8_t *t8 = (grub_uint8_t *) target;
  1198. grub_int64_t off;
  1199. /*
  1200. * Instructions and instruction encoding are documented in the RISC-V
  1201. * specification. This file is based on version 2.2:
  1202. *
  1203. * https://github.com/riscv/riscv-isa-manual/blob/master/release/riscv-spec-v2.2.pdf
  1204. */
  1205. sym_addr += addend;
  1206. off = sym_addr - target_section_addr - offset - image_target->vaddr_offset;
  1207. switch (ELF_R_TYPE (info))
  1208. {
  1209. case R_RISCV_ADD8:
  1210. *t8 = *t8 + sym_addr;
  1211. break;
  1212. case R_RISCV_ADD16:
  1213. *t16 = grub_host_to_target16 (grub_target_to_host16 (*t16) + sym_addr);
  1214. break;
  1215. case R_RISCV_32:
  1216. case R_RISCV_ADD32:
  1217. *t32 = grub_host_to_target32 (grub_target_to_host32 (*t32) + sym_addr);
  1218. break;
  1219. case R_RISCV_64:
  1220. case R_RISCV_ADD64:
  1221. *t64 = grub_host_to_target64 (grub_target_to_host64 (*t64) + sym_addr);
  1222. break;
  1223. case R_RISCV_SUB8:
  1224. *t8 = sym_addr - *t8;
  1225. break;
  1226. case R_RISCV_SUB16:
  1227. *t16 = grub_host_to_target16 (grub_target_to_host16 (*t16) - sym_addr);
  1228. break;
  1229. case R_RISCV_SUB32:
  1230. *t32 = grub_host_to_target32 (grub_target_to_host32 (*t32) - sym_addr);
  1231. break;
  1232. case R_RISCV_SUB64:
  1233. *t64 = grub_host_to_target64 (grub_target_to_host64 (*t64) - sym_addr);
  1234. break;
  1235. case R_RISCV_BRANCH:
  1236. {
  1237. grub_uint32_t imm12 = (off & 0x1000) << (31 - 12);
  1238. grub_uint32_t imm11 = (off & 0x800) >> (11 - 7);
  1239. grub_uint32_t imm10_5 = (off & 0x7e0) << (30 - 10);
  1240. grub_uint32_t imm4_1 = (off & 0x1e) << (11 - 4);
  1241. *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0x1fff07f)
  1242. | imm12 | imm11 | imm10_5 | imm4_1);
  1243. }
  1244. break;
  1245. case R_RISCV_JAL:
  1246. {
  1247. grub_uint32_t imm20 = (off & 0x100000) << (31 - 20);
  1248. grub_uint32_t imm19_12 = (off & 0xff000);
  1249. grub_uint32_t imm11 = (off & 0x800) << (20 - 11);
  1250. grub_uint32_t imm10_1 = (off & 0x7fe) << (30 - 10);
  1251. *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0xfff)
  1252. | imm20 | imm19_12 | imm11 | imm10_1);
  1253. }
  1254. break;
  1255. case R_RISCV_CALL:
  1256. case R_RISCV_CALL_PLT:
  1257. {
  1258. grub_uint32_t hi20, lo12;
  1259. if (off != (grub_int32_t)off)
  1260. grub_util_error ("target %lx not reachable from pc=%lx", (long)sym_addr, (long)((char *)target - (char *)e));
  1261. hi20 = (off + 0x800) & 0xfffff000;
  1262. lo12 = (off - hi20) & 0xfff;
  1263. t32[0] = grub_host_to_target32 ((grub_target_to_host32 (t32[0]) & 0xfff) | hi20);
  1264. t32[1] = grub_host_to_target32 ((grub_target_to_host32 (t32[1]) & 0xfffff) | (lo12 << 20));
  1265. }
  1266. break;
  1267. case R_RISCV_RVC_BRANCH:
  1268. {
  1269. grub_uint16_t imm8 = (off & 0x100) << (12 - 8);
  1270. grub_uint16_t imm7_6 = (off & 0xc0) >> (6 - 5);
  1271. grub_uint16_t imm5 = (off & 0x20) >> (5 - 2);
  1272. grub_uint16_t imm4_3 = (off & 0x18) << (12 - 5);
  1273. grub_uint16_t imm2_1 = (off & 0x6) << (12 - 10);
  1274. *t16 = grub_host_to_target16 ((grub_target_to_host16 (*t16) & 0xe383)
  1275. | imm8 | imm7_6 | imm5 | imm4_3 | imm2_1);
  1276. }
  1277. break;
  1278. case R_RISCV_RVC_JUMP:
  1279. {
  1280. grub_uint16_t imm11 = (off & 0x800) << (12 - 11);
  1281. grub_uint16_t imm10 = (off & 0x400) >> (10 - 8);
  1282. grub_uint16_t imm9_8 = (off & 0x300) << (12 - 11);
  1283. grub_uint16_t imm7 = (off & 0x80) >> (7 - 6);
  1284. grub_uint16_t imm6 = (off & 0x40) << (12 - 11);
  1285. grub_uint16_t imm5 = (off & 0x20) >> (5 - 2);
  1286. grub_uint16_t imm4 = (off & 0x10) << (12 - 5);
  1287. grub_uint16_t imm3_1 = (off & 0xe) << (12 - 10);
  1288. *t16 = grub_host_to_target16 ((grub_target_to_host16 (*t16) & 0xe003)
  1289. | imm11 | imm10 | imm9_8 | imm7 | imm6
  1290. | imm5 | imm4 | imm3_1);
  1291. }
  1292. break;
  1293. case R_RISCV_PCREL_HI20:
  1294. {
  1295. grub_int32_t hi20;
  1296. if (off != (grub_int32_t)off)
  1297. grub_util_error ("target %lx not reachable from pc=%lx", (long)sym_addr, (long)((char *)target - (char *)e));
  1298. hi20 = (off + 0x800) & 0xfffff000;
  1299. *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0xfff) | hi20);
  1300. }
  1301. break;
  1302. case R_RISCV_PCREL_LO12_I:
  1303. case R_RISCV_PCREL_LO12_S:
  1304. {
  1305. Elf_Rela *rel2;
  1306. Elf_Word k;
  1307. /* Search backwards for matching HI20 reloc. */
  1308. for (k = j, rel2 = (Elf_Rela *) ((char *) r - r_size);
  1309. k > 0;
  1310. k--, rel2 = (Elf_Rela *) ((char *) rel2 - r_size))
  1311. {
  1312. Elf_Addr rel2_info;
  1313. Elf_Addr rel2_offset;
  1314. Elf_Addr rel2_sym_addr;
  1315. Elf_Addr rel2_addend;
  1316. Elf_Addr rel2_loc;
  1317. grub_int64_t rel2_off;
  1318. rel2_offset = grub_target_to_host (rel2->r_offset);
  1319. rel2_info = grub_target_to_host (rel2->r_info);
  1320. rel2_loc = target_section_addr + rel2_offset + image_target->vaddr_offset;
  1321. if (ELF_R_TYPE (rel2_info) == R_RISCV_PCREL_HI20
  1322. && rel2_loc == sym_addr)
  1323. {
  1324. rel2_sym_addr = SUFFIX (get_symbol_address)
  1325. (e, smd->symtab, ELF_R_SYM (rel2_info),
  1326. image_target);
  1327. rel2_addend = (s->sh_type == grub_target_to_host32 (SHT_RELA)) ?
  1328. grub_target_to_host (rel2->r_addend) : 0;
  1329. rel2_off = rel2_sym_addr + rel2_addend - rel2_loc;
  1330. off = rel2_off - ((rel2_off + 0x800) & 0xfffff000);
  1331. if (ELF_R_TYPE (info) == R_RISCV_PCREL_LO12_I)
  1332. *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0xfffff) | (off & 0xfff) << 20);
  1333. else
  1334. {
  1335. grub_uint32_t imm11_5 = (off & 0xfe0) << (31 - 11);
  1336. grub_uint32_t imm4_0 = (off & 0x1f) << (11 - 4);
  1337. *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0x1fff07f) | imm11_5 | imm4_0);
  1338. }
  1339. break;
  1340. }
  1341. }
  1342. if (k == 0)
  1343. grub_util_error ("cannot find matching HI20 relocation");
  1344. }
  1345. break;
  1346. case R_RISCV_HI20:
  1347. *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0xfff) | (((grub_int32_t) sym_addr + 0x800) & 0xfffff000));
  1348. break;
  1349. case R_RISCV_LO12_I:
  1350. {
  1351. grub_int32_t lo12 = (grub_int32_t) sym_addr - (((grub_int32_t) sym_addr + 0x800) & 0xfffff000);
  1352. *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0xfffff) | ((lo12 & 0xfff) << 20));
  1353. }
  1354. break;
  1355. case R_RISCV_LO12_S:
  1356. {
  1357. grub_int32_t lo12 = (grub_int32_t) sym_addr - (((grub_int32_t) sym_addr + 0x800) & 0xfffff000);
  1358. grub_uint32_t imm11_5 = (lo12 & 0xfe0) << (31 - 11);
  1359. grub_uint32_t imm4_0 = (lo12 & 0x1f) << (11 - 4);
  1360. *t32 = grub_host_to_target32 ((grub_target_to_host32 (*t32) & 0x1fff07f) | imm11_5 | imm4_0);
  1361. }
  1362. break;
  1363. case R_RISCV_RELAX:
  1364. break;
  1365. default:
  1366. grub_util_error (_("relocation 0x%x is not implemented yet"),
  1367. (unsigned int) ELF_R_TYPE (info));
  1368. break;
  1369. }
  1370. break;
  1371. }
  1372. default:
  1373. grub_util_error ("unknown architecture type %d",
  1374. image_target->elf_target);
  1375. }
  1376. }
  1377. }
  1378. }
  1379. /* Add a PE32's fixup entry for a relocation. Return the resulting address
  1380. after having written to the file OUT. */
  1381. static Elf_Addr
  1382. add_fixup_entry (struct fixup_block_list **cblock, grub_uint16_t type,
  1383. Elf_Addr addr, int flush, Elf_Addr current_address,
  1384. const struct grub_install_image_target_desc *image_target)
  1385. {
  1386. struct grub_pe32_fixup_block *b;
  1387. b = &((*cblock)->b);
  1388. /* First, check if it is necessary to write out the current block. */
  1389. if ((*cblock)->state)
  1390. {
  1391. if (flush || addr < b->page_rva || b->page_rva + 0x1000 <= addr)
  1392. {
  1393. grub_uint32_t size;
  1394. if (flush)
  1395. {
  1396. /* Add as much padding as necessary to align the address
  1397. with a section boundary. */
  1398. Elf_Addr next_address;
  1399. unsigned padding_size;
  1400. size_t cur_index;
  1401. next_address = current_address + b->block_size;
  1402. padding_size = ((ALIGN_UP (next_address, image_target->section_align)
  1403. - next_address)
  1404. >> 1);
  1405. cur_index = ((b->block_size - sizeof (*b)) >> 1);
  1406. grub_util_info ("adding %d padding fixup entries", padding_size);
  1407. while (padding_size--)
  1408. {
  1409. b->entries[cur_index++] = 0;
  1410. b->block_size += 2;
  1411. }
  1412. }
  1413. else while (b->block_size & (8 - 1))
  1414. {
  1415. /* If not aligned with a 32-bit boundary, add
  1416. a padding entry. */
  1417. size_t cur_index;
  1418. grub_util_info ("adding a padding fixup entry");
  1419. cur_index = ((b->block_size - sizeof (*b)) >> 1);
  1420. b->entries[cur_index] = 0;
  1421. b->block_size += 2;
  1422. }
  1423. /* Flush it. */
  1424. grub_util_info ("writing %d bytes of a fixup block starting at 0x%x",
  1425. b->block_size, b->page_rva);
  1426. size = b->block_size;
  1427. current_address += size;
  1428. b->page_rva = grub_host_to_target32 (b->page_rva);
  1429. b->block_size = grub_host_to_target32 (b->block_size);
  1430. (*cblock)->next = xmalloc (sizeof (**cblock) + 2 * 0x1000);
  1431. memset ((*cblock)->next, 0, sizeof (**cblock) + 2 * 0x1000);
  1432. *cblock = (*cblock)->next;
  1433. }
  1434. }
  1435. b = &((*cblock)->b);
  1436. if (! flush)
  1437. {
  1438. grub_uint16_t entry;
  1439. size_t cur_index;
  1440. /* If not allocated yet, allocate a block with enough entries. */
  1441. if (! (*cblock)->state)
  1442. {
  1443. (*cblock)->state = 1;
  1444. /* The spec does not mention the requirement of a Page RVA.
  1445. Here, align the address with a 4K boundary for safety. */
  1446. b->page_rva = (addr & ~(0x1000 - 1));
  1447. b->block_size = sizeof (*b);
  1448. }
  1449. /* Sanity check. */
  1450. if (b->block_size >= sizeof (*b) + 2 * 0x1000)
  1451. grub_util_error ("too many fixup entries");
  1452. /* Add a new entry. */
  1453. cur_index = ((b->block_size - sizeof (*b)) >> 1);
  1454. entry = GRUB_PE32_FIXUP_ENTRY (type, addr - b->page_rva);
  1455. b->entries[cur_index] = grub_host_to_target16 (entry);
  1456. b->block_size += 2;
  1457. }
  1458. return current_address;
  1459. }
  1460. struct raw_reloc
  1461. {
  1462. struct raw_reloc *next;
  1463. grub_uint32_t offset;
  1464. enum raw_reloc_type {
  1465. RAW_RELOC_NONE = -1,
  1466. RAW_RELOC_32 = 0,
  1467. RAW_RELOC_MAX = 1,
  1468. } type;
  1469. };
  1470. struct translate_context
  1471. {
  1472. /* PE */
  1473. struct fixup_block_list *lst, *lst0;
  1474. Elf_Addr current_address;
  1475. /* Raw */
  1476. struct raw_reloc *raw_relocs;
  1477. };
  1478. static void
  1479. translate_reloc_start (struct translate_context *ctx,
  1480. const struct grub_install_image_target_desc *image_target)
  1481. {
  1482. grub_memset (ctx, 0, sizeof (*ctx));
  1483. if (image_target->id == IMAGE_EFI)
  1484. {
  1485. ctx->lst = ctx->lst0 = xmalloc (sizeof (*ctx->lst) + 2 * 0x1000);
  1486. memset (ctx->lst, 0, sizeof (*ctx->lst) + 2 * 0x1000);
  1487. ctx->current_address = 0;
  1488. }
  1489. }
  1490. static void
  1491. translate_relocation_pe (struct translate_context *ctx,
  1492. Elf_Addr addr,
  1493. Elf_Addr info,
  1494. const struct grub_install_image_target_desc *image_target)
  1495. {
  1496. /* Necessary to relocate only absolute addresses. */
  1497. switch (image_target->elf_target)
  1498. {
  1499. case EM_386:
  1500. if (ELF_R_TYPE (info) == R_386_32)
  1501. {
  1502. grub_util_info ("adding a relocation entry for 0x%"
  1503. GRUB_HOST_PRIxLONG_LONG,
  1504. (unsigned long long) addr);
  1505. ctx->current_address
  1506. = add_fixup_entry (&ctx->lst,
  1507. GRUB_PE32_REL_BASED_HIGHLOW,
  1508. addr, 0, ctx->current_address,
  1509. image_target);
  1510. }
  1511. break;
  1512. case EM_X86_64:
  1513. if ((ELF_R_TYPE (info) == R_X86_64_32) ||
  1514. (ELF_R_TYPE (info) == R_X86_64_32S))
  1515. {
  1516. grub_util_error ("can\'t add fixup entry for R_X86_64_32(S)");
  1517. }
  1518. else if (ELF_R_TYPE (info) == R_X86_64_64)
  1519. {
  1520. grub_util_info ("adding a relocation entry for 0x%"
  1521. GRUB_HOST_PRIxLONG_LONG,
  1522. (unsigned long long) addr);
  1523. ctx->current_address
  1524. = add_fixup_entry (&ctx->lst,
  1525. GRUB_PE32_REL_BASED_DIR64,
  1526. addr,
  1527. 0, ctx->current_address,
  1528. image_target);
  1529. }
  1530. break;
  1531. case EM_IA_64:
  1532. switch (ELF_R_TYPE (info))
  1533. {
  1534. case R_IA64_PCREL64LSB:
  1535. case R_IA64_LDXMOV:
  1536. case R_IA64_PCREL21B:
  1537. case R_IA64_LTOFF_FPTR22:
  1538. case R_IA64_LTOFF22X:
  1539. case R_IA64_LTOFF22:
  1540. case R_IA64_GPREL22:
  1541. case R_IA64_GPREL64I:
  1542. case R_IA64_SEGREL64LSB:
  1543. break;
  1544. case R_IA64_FPTR64LSB:
  1545. case R_IA64_DIR64LSB:
  1546. #if 1
  1547. {
  1548. grub_util_info ("adding a relocation entry for 0x%"
  1549. GRUB_HOST_PRIxLONG_LONG,
  1550. (unsigned long long) addr);
  1551. ctx->current_address
  1552. = add_fixup_entry (&ctx->lst,
  1553. GRUB_PE32_REL_BASED_DIR64,
  1554. addr,
  1555. 0, ctx->current_address,
  1556. image_target);
  1557. }
  1558. #endif
  1559. break;
  1560. default:
  1561. grub_util_error (_("relocation 0x%x is not implemented yet"),
  1562. (unsigned int) ELF_R_TYPE (info));
  1563. break;
  1564. }
  1565. break;
  1566. case EM_AARCH64:
  1567. #if defined(MKIMAGE_ELF64)
  1568. switch (ELF_R_TYPE (info))
  1569. {
  1570. case R_AARCH64_ABS64:
  1571. {
  1572. ctx->current_address
  1573. = add_fixup_entry (&ctx->lst,
  1574. GRUB_PE32_REL_BASED_DIR64,
  1575. addr, 0, ctx->current_address,
  1576. image_target);
  1577. }
  1578. break;
  1579. /* Relative relocations do not require fixup entries. */
  1580. case R_AARCH64_CALL26:
  1581. case R_AARCH64_JUMP26:
  1582. case R_AARCH64_PREL32:
  1583. break;
  1584. /* Page-relative relocations do not require fixup entries. */
  1585. case R_AARCH64_ADR_PREL_PG_HI21:
  1586. /* We page-align the whole kernel, so no need
  1587. for fixup entries.
  1588. */
  1589. case R_AARCH64_ADD_ABS_LO12_NC:
  1590. case R_AARCH64_LDST64_ABS_LO12_NC:
  1591. break;
  1592. /* GOT is relocated separately. */
  1593. case R_AARCH64_ADR_GOT_PAGE:
  1594. case R_AARCH64_LD64_GOT_LO12_NC:
  1595. break;
  1596. default:
  1597. grub_util_error (_("relocation 0x%x is not implemented yet"),
  1598. (unsigned int) ELF_R_TYPE (info));
  1599. break;
  1600. }
  1601. #endif /* defined(MKIMAGE_ELF64) */
  1602. break;
  1603. case EM_LOONGARCH:
  1604. #if defined(MKIMAGE_ELF64)
  1605. switch (ELF_R_TYPE (info))
  1606. {
  1607. case R_LARCH_64:
  1608. {
  1609. ctx->current_address = add_fixup_entry (&ctx->lst,
  1610. GRUB_PE32_REL_BASED_DIR64,
  1611. addr, 0, ctx->current_address,
  1612. image_target);
  1613. }
  1614. break;
  1615. case R_LARCH_MARK_LA:
  1616. {
  1617. ctx->current_address = add_fixup_entry (&ctx->lst,
  1618. GRUB_PE32_REL_BASED_LOONGARCH64_MARK_LA,
  1619. addr, 0, ctx->current_address,
  1620. image_target);
  1621. }
  1622. break;
  1623. /* Relative relocations do not require fixup entries. */
  1624. case R_LARCH_NONE:
  1625. case R_LARCH_SOP_PUSH_PCREL:
  1626. case R_LARCH_SOP_PUSH_ABSOLUTE:
  1627. case R_LARCH_SOP_PUSH_PLT_PCREL:
  1628. case R_LARCH_SOP_SUB:
  1629. case R_LARCH_SOP_SL:
  1630. case R_LARCH_SOP_SR:
  1631. case R_LARCH_SOP_ADD:
  1632. case R_LARCH_SOP_AND:
  1633. case R_LARCH_SOP_IF_ELSE:
  1634. case R_LARCH_SOP_POP_32_S_10_5:
  1635. case R_LARCH_SOP_POP_32_U_10_12:
  1636. case R_LARCH_SOP_POP_32_S_10_12:
  1637. case R_LARCH_SOP_POP_32_S_10_16:
  1638. case R_LARCH_SOP_POP_32_S_10_16_S2:
  1639. case R_LARCH_SOP_POP_32_S_5_20:
  1640. case R_LARCH_SOP_POP_32_S_0_5_10_16_S2:
  1641. case R_LARCH_SOP_POP_32_S_0_10_10_16_S2:
  1642. case R_LARCH_B26:
  1643. case R_LARCH_ABS_HI20:
  1644. case R_LARCH_ABS_LO12:
  1645. case R_LARCH_ABS64_LO20:
  1646. case R_LARCH_ABS64_HI12:
  1647. case R_LARCH_PCALA_HI20:
  1648. case R_LARCH_PCALA_LO12:
  1649. grub_util_info (" %s: not adding fixup: 0x%08x : 0x%08x",
  1650. __FUNCTION__,
  1651. (unsigned int) addr,
  1652. (unsigned int) ctx->current_address);
  1653. break;
  1654. default:
  1655. grub_util_error (_("relocation 0x%x is not implemented yet"),
  1656. (unsigned int) ELF_R_TYPE (info));
  1657. break;
  1658. }
  1659. #endif /* defined(MKIMAGE_ELF64) */
  1660. break;
  1661. #if defined(MKIMAGE_ELF32)
  1662. case EM_ARM:
  1663. switch (ELF_R_TYPE (info))
  1664. {
  1665. case R_ARM_V4BX:
  1666. /* Relative relocations do not require fixup entries. */
  1667. case R_ARM_JUMP24:
  1668. case R_ARM_THM_CALL:
  1669. case R_ARM_THM_JUMP19:
  1670. case R_ARM_THM_JUMP24:
  1671. case R_ARM_CALL:
  1672. {
  1673. grub_util_info (" %s: not adding fixup: 0x%08x : 0x%08x", __FUNCTION__, (unsigned int) addr, (unsigned int) ctx->current_address);
  1674. }
  1675. break;
  1676. /* Create fixup entry for PE/COFF loader */
  1677. case R_ARM_ABS32:
  1678. {
  1679. ctx->current_address
  1680. = add_fixup_entry (&ctx->lst,
  1681. GRUB_PE32_REL_BASED_HIGHLOW,
  1682. addr, 0, ctx->current_address,
  1683. image_target);
  1684. }
  1685. break;
  1686. default:
  1687. grub_util_error (_("relocation 0x%x is not implemented yet"),
  1688. (unsigned int) ELF_R_TYPE (info));
  1689. break;
  1690. }
  1691. break;
  1692. #endif /* defined(MKIMAGE_ELF32) */
  1693. case EM_RISCV:
  1694. switch (ELF_R_TYPE (info))
  1695. {
  1696. case R_RISCV_32:
  1697. {
  1698. ctx->current_address
  1699. = add_fixup_entry (&ctx->lst,
  1700. GRUB_PE32_REL_BASED_HIGHLOW,
  1701. addr, 0, ctx->current_address,
  1702. image_target);
  1703. }
  1704. break;
  1705. case R_RISCV_64:
  1706. {
  1707. ctx->current_address
  1708. = add_fixup_entry (&ctx->lst,
  1709. GRUB_PE32_REL_BASED_DIR64,
  1710. addr, 0, ctx->current_address,
  1711. image_target);
  1712. }
  1713. break;
  1714. /* Relative relocations do not require fixup entries. */
  1715. case R_RISCV_BRANCH:
  1716. case R_RISCV_JAL:
  1717. case R_RISCV_CALL:
  1718. case R_RISCV_CALL_PLT:
  1719. case R_RISCV_PCREL_HI20:
  1720. case R_RISCV_PCREL_LO12_I:
  1721. case R_RISCV_PCREL_LO12_S:
  1722. case R_RISCV_RVC_BRANCH:
  1723. case R_RISCV_RVC_JUMP:
  1724. case R_RISCV_ADD32:
  1725. case R_RISCV_SUB32:
  1726. grub_util_info (" %s: not adding fixup: 0x%08x : 0x%08x", __FUNCTION__, (unsigned int) addr, (unsigned int) ctx->current_address);
  1727. break;
  1728. case R_RISCV_HI20:
  1729. {
  1730. ctx->current_address
  1731. = add_fixup_entry (&ctx->lst,
  1732. GRUB_PE32_REL_BASED_RISCV_HI20,
  1733. addr, 0, ctx->current_address,
  1734. image_target);
  1735. }
  1736. break;
  1737. case R_RISCV_LO12_I:
  1738. {
  1739. ctx->current_address
  1740. = add_fixup_entry (&ctx->lst,
  1741. GRUB_PE32_REL_BASED_RISCV_LOW12I,
  1742. addr, 0, ctx->current_address,
  1743. image_target);
  1744. }
  1745. break;
  1746. case R_RISCV_LO12_S:
  1747. {
  1748. ctx->current_address
  1749. = add_fixup_entry (&ctx->lst,
  1750. GRUB_PE32_REL_BASED_RISCV_LOW12S,
  1751. addr, 0, ctx->current_address,
  1752. image_target);
  1753. }
  1754. break;
  1755. case R_RISCV_RELAX:
  1756. break;
  1757. default:
  1758. grub_util_error (_("relocation 0x%x is not implemented yet"),
  1759. (unsigned int) ELF_R_TYPE (info));
  1760. break;
  1761. }
  1762. break;
  1763. default:
  1764. grub_util_error ("unknown machine type 0x%x", image_target->elf_target);
  1765. }
  1766. }
  1767. static enum raw_reloc_type
  1768. classify_raw_reloc (Elf_Addr info,
  1769. const struct grub_install_image_target_desc *image_target)
  1770. {
  1771. /* Necessary to relocate only absolute addresses. */
  1772. switch (image_target->elf_target)
  1773. {
  1774. case EM_ARM:
  1775. switch (ELF_R_TYPE (info))
  1776. {
  1777. case R_ARM_V4BX:
  1778. case R_ARM_JUMP24:
  1779. case R_ARM_THM_CALL:
  1780. case R_ARM_THM_JUMP19:
  1781. case R_ARM_THM_JUMP24:
  1782. case R_ARM_CALL:
  1783. return RAW_RELOC_NONE;
  1784. case R_ARM_ABS32:
  1785. return RAW_RELOC_32;
  1786. default:
  1787. grub_util_error (_("relocation 0x%x is not implemented yet"),
  1788. (unsigned int) ELF_R_TYPE (info));
  1789. break;
  1790. }
  1791. break;
  1792. default:
  1793. grub_util_error ("unknown machine type 0x%x", image_target->elf_target);
  1794. }
  1795. }
  1796. static void
  1797. translate_relocation_raw (struct translate_context *ctx,
  1798. Elf_Addr addr,
  1799. Elf_Addr info,
  1800. const struct grub_install_image_target_desc *image_target)
  1801. {
  1802. enum raw_reloc_type class = classify_raw_reloc (info, image_target);
  1803. struct raw_reloc *rel;
  1804. if (class == RAW_RELOC_NONE)
  1805. return;
  1806. rel = xmalloc (sizeof (*rel));
  1807. rel->next = ctx->raw_relocs;
  1808. rel->type = class;
  1809. rel->offset = addr;
  1810. ctx->raw_relocs = rel;
  1811. }
  1812. static void
  1813. translate_relocation (struct translate_context *ctx,
  1814. Elf_Addr addr,
  1815. Elf_Addr info,
  1816. const struct grub_install_image_target_desc *image_target)
  1817. {
  1818. if (image_target->id == IMAGE_EFI)
  1819. translate_relocation_pe (ctx, addr, info, image_target);
  1820. else
  1821. translate_relocation_raw (ctx, addr, info, image_target);
  1822. }
  1823. static void
  1824. finish_reloc_translation_pe (struct translate_context *ctx, struct grub_mkimage_layout *layout,
  1825. const struct grub_install_image_target_desc *image_target)
  1826. {
  1827. ctx->current_address = add_fixup_entry (&ctx->lst, 0, 0, 1, ctx->current_address, image_target);
  1828. {
  1829. grub_uint8_t *ptr;
  1830. layout->reloc_section = ptr = xmalloc (ctx->current_address);
  1831. for (ctx->lst = ctx->lst0; ctx->lst; ctx->lst = ctx->lst->next)
  1832. if (ctx->lst->state)
  1833. {
  1834. memcpy (ptr, &ctx->lst->b, grub_target_to_host32 (ctx->lst->b.block_size));
  1835. ptr += grub_target_to_host32 (ctx->lst->b.block_size);
  1836. }
  1837. assert ((ctx->current_address + (grub_uint8_t *) layout->reloc_section) == ptr);
  1838. }
  1839. for (ctx->lst = ctx->lst0; ctx->lst; )
  1840. {
  1841. struct fixup_block_list *next;
  1842. next = ctx->lst->next;
  1843. free (ctx->lst);
  1844. ctx->lst = next;
  1845. }
  1846. layout->reloc_size = ctx->current_address;
  1847. if (image_target->elf_target == EM_ARM && layout->reloc_size > GRUB_KERNEL_ARM_STACK_SIZE)
  1848. grub_util_error ("Reloc section (%d) is bigger than stack size (%d). "
  1849. "This breaks assembly assumptions. Please increase stack size",
  1850. (int) layout->reloc_size,
  1851. (int) GRUB_KERNEL_ARM_STACK_SIZE);
  1852. }
  1853. /*
  1854. Layout:
  1855. <type 0 relocations>
  1856. <fffffffe>
  1857. <type 1 relocations>
  1858. <fffffffe>
  1859. ...
  1860. <type n relocations>
  1861. <ffffffff>
  1862. each relocation starts with 32-bit offset. Rest depends on relocation.
  1863. mkimage stops when it sees first unknown type or end marker.
  1864. This allows images to be created with mismatched mkimage and
  1865. kernel as long as no relocations are present in kernel that mkimage
  1866. isn't aware of (in which case mkimage aborts).
  1867. This also allows simple assembly to do the relocs.
  1868. */
  1869. #define RAW_SEPARATOR 0xfffffffe
  1870. #define RAW_END_MARKER 0xffffffff
  1871. static void
  1872. finish_reloc_translation_raw (struct translate_context *ctx, struct grub_mkimage_layout *layout,
  1873. const struct grub_install_image_target_desc *image_target)
  1874. {
  1875. size_t count = 0, sz;
  1876. enum raw_reloc_type highest = RAW_RELOC_NONE;
  1877. enum raw_reloc_type curtype;
  1878. struct raw_reloc *cur;
  1879. grub_uint32_t *p;
  1880. if (!ctx->raw_relocs)
  1881. {
  1882. layout->reloc_section = p = xmalloc (sizeof (grub_uint32_t));
  1883. p[0] = RAW_END_MARKER;
  1884. layout->reloc_size = sizeof (grub_uint32_t);
  1885. return;
  1886. }
  1887. for (cur = ctx->raw_relocs; cur; cur = cur->next)
  1888. {
  1889. count++;
  1890. if (cur->type > highest)
  1891. highest = cur->type;
  1892. }
  1893. /* highest separators, count relocations and one end marker. */
  1894. sz = (highest + count + 1) * sizeof (grub_uint32_t);
  1895. layout->reloc_section = p = xmalloc (sz);
  1896. for (curtype = 0; curtype <= highest; curtype++)
  1897. {
  1898. /* Support for special cases would go here. */
  1899. for (cur = ctx->raw_relocs; cur; cur = cur->next)
  1900. if (cur->type == curtype)
  1901. {
  1902. *p++ = cur->offset;
  1903. }
  1904. *p++ = RAW_SEPARATOR;
  1905. }
  1906. *--p = RAW_END_MARKER;
  1907. layout->reloc_size = sz;
  1908. }
  1909. static void
  1910. finish_reloc_translation (struct translate_context *ctx, struct grub_mkimage_layout *layout,
  1911. const struct grub_install_image_target_desc *image_target)
  1912. {
  1913. if (image_target->id == IMAGE_EFI)
  1914. finish_reloc_translation_pe (ctx, layout, image_target);
  1915. else
  1916. finish_reloc_translation_raw (ctx, layout, image_target);
  1917. }
  1918. static void
  1919. create_u64_fixups (struct translate_context *ctx,
  1920. Elf_Addr jumpers, grub_size_t njumpers,
  1921. const struct grub_install_image_target_desc *image_target)
  1922. {
  1923. unsigned i;
  1924. assert (image_target->id == IMAGE_EFI);
  1925. for (i = 0; i < njumpers; i++)
  1926. ctx->current_address = add_fixup_entry (&ctx->lst,
  1927. GRUB_PE32_REL_BASED_DIR64,
  1928. jumpers + 8 * i,
  1929. 0, ctx->current_address,
  1930. image_target);
  1931. }
  1932. /* Make a .reloc section. */
  1933. static void
  1934. make_reloc_section (Elf_Ehdr *e, struct grub_mkimage_layout *layout,
  1935. struct section_metadata *smd,
  1936. const struct grub_install_image_target_desc *image_target)
  1937. {
  1938. unsigned i;
  1939. Elf_Shdr *s;
  1940. struct translate_context ctx;
  1941. translate_reloc_start (&ctx, image_target);
  1942. for (i = 0, s = smd->sections; i < smd->num_sections;
  1943. i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
  1944. if ((grub_target_to_host32 (s->sh_type) == SHT_REL) ||
  1945. (grub_target_to_host32 (s->sh_type) == SHT_RELA))
  1946. {
  1947. Elf_Rel *r;
  1948. Elf_Word rtab_size, r_size, num_rs;
  1949. Elf_Off rtab_offset;
  1950. Elf_Addr section_address;
  1951. Elf_Word j;
  1952. if (!SUFFIX (is_kept_reloc_section) (s, image_target, smd))
  1953. {
  1954. grub_util_info ("not translating the skipped relocation section %s",
  1955. smd->strtab + grub_le_to_cpu32 (s->sh_name));
  1956. continue;
  1957. }
  1958. grub_util_info ("translating the relocation section %s",
  1959. smd->strtab + grub_le_to_cpu32 (s->sh_name));
  1960. rtab_size = grub_target_to_host (s->sh_size);
  1961. r_size = grub_target_to_host (s->sh_entsize);
  1962. rtab_offset = grub_target_to_host (s->sh_offset);
  1963. num_rs = rtab_size / r_size;
  1964. section_address = smd->vaddrs[grub_le_to_cpu32 (s->sh_info)];
  1965. for (j = 0, r = (Elf_Rel *) ((char *) e + rtab_offset);
  1966. j < num_rs;
  1967. j++, r = (Elf_Rel *) ((char *) r + r_size))
  1968. {
  1969. Elf_Addr info;
  1970. Elf_Addr offset;
  1971. Elf_Addr addr;
  1972. offset = grub_target_to_host (r->r_offset);
  1973. info = grub_target_to_host (r->r_info);
  1974. addr = section_address + offset;
  1975. translate_relocation (&ctx, addr, info, image_target);
  1976. }
  1977. }
  1978. if (image_target->elf_target == EM_IA_64)
  1979. create_u64_fixups (&ctx,
  1980. layout->ia64jmp_off
  1981. + image_target->vaddr_offset,
  1982. 2 * layout->ia64jmpnum,
  1983. image_target);
  1984. if (image_target->elf_target == EM_IA_64 || image_target->elf_target == EM_AARCH64)
  1985. create_u64_fixups (&ctx,
  1986. layout->got_off
  1987. + image_target->vaddr_offset,
  1988. (layout->got_size / 8),
  1989. image_target);
  1990. finish_reloc_translation (&ctx, layout, image_target);
  1991. }
  1992. /* Determine if this section is a text section. Return false if this
  1993. section is not allocated. */
  1994. static int
  1995. SUFFIX (is_text_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
  1996. {
  1997. if (!is_relocatable (image_target)
  1998. && grub_target_to_host32 (s->sh_type) != SHT_PROGBITS)
  1999. return 0;
  2000. return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
  2001. == (SHF_EXECINSTR | SHF_ALLOC));
  2002. }
  2003. /* Determine if this section is a data section. */
  2004. static int
  2005. SUFFIX (is_data_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
  2006. {
  2007. if (!is_relocatable (image_target)
  2008. && grub_target_to_host32 (s->sh_type) != SHT_PROGBITS)
  2009. return 0;
  2010. return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
  2011. == SHF_ALLOC) && !(grub_target_to_host32 (s->sh_type) == SHT_NOBITS);
  2012. }
  2013. static int
  2014. SUFFIX (is_bss_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
  2015. {
  2016. if (!is_relocatable (image_target))
  2017. return 0;
  2018. return ((grub_target_to_host (s->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC))
  2019. == SHF_ALLOC) && (grub_target_to_host32 (s->sh_type) == SHT_NOBITS);
  2020. }
  2021. /* Determine if a section is going to be in the final output */
  2022. static int
  2023. SUFFIX (is_kept_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target)
  2024. {
  2025. /* We keep .text and .data */
  2026. if (SUFFIX (is_text_section) (s, image_target)
  2027. || SUFFIX (is_data_section) (s, image_target))
  2028. return 1;
  2029. /*
  2030. * And we keep .bss if we're producing PE binaries or the target doesn't
  2031. * have a relocating loader. Platforms other than EFI and U-boot shouldn't
  2032. * have .bss in their binaries as we build with -Wl,-Ttext.
  2033. */
  2034. if (SUFFIX (is_bss_section) (s, image_target)
  2035. && (image_target->id == IMAGE_EFI || !is_relocatable (image_target)))
  2036. return 1;
  2037. /* Otherwise this is not a section we're keeping in the final output. */
  2038. return 0;
  2039. }
  2040. static int
  2041. SUFFIX (is_kept_reloc_section) (Elf_Shdr *s, const struct grub_install_image_target_desc *image_target,
  2042. struct section_metadata *smd)
  2043. {
  2044. int i;
  2045. int r = 0;
  2046. const char *name = smd->strtab + grub_host_to_target32 (s->sh_name);
  2047. if (!strncmp (name, ".rela.", 6))
  2048. name += 5;
  2049. else if (!strncmp (name, ".rel.", 5))
  2050. name += 4;
  2051. else
  2052. return 1;
  2053. for (i = 0, s = smd->sections; i < smd->num_sections;
  2054. i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
  2055. {
  2056. const char *sname = smd->strtab + grub_host_to_target32 (s->sh_name);
  2057. if (strcmp (sname, name))
  2058. continue;
  2059. return SUFFIX (is_kept_section) (s, image_target);
  2060. }
  2061. return r;
  2062. }
  2063. /* Return if the ELF header is valid. */
  2064. static int
  2065. SUFFIX (check_elf_header) (Elf_Ehdr *e, size_t size, const struct grub_install_image_target_desc *image_target)
  2066. {
  2067. if (size < sizeof (*e)
  2068. || e->e_ident[EI_MAG0] != ELFMAG0
  2069. || e->e_ident[EI_MAG1] != ELFMAG1
  2070. || e->e_ident[EI_MAG2] != ELFMAG2
  2071. || e->e_ident[EI_MAG3] != ELFMAG3
  2072. || e->e_ident[EI_VERSION] != EV_CURRENT
  2073. || e->e_ident[EI_CLASS] != ELFCLASSXX
  2074. || e->e_version != grub_host_to_target32 (EV_CURRENT))
  2075. return 0;
  2076. return 1;
  2077. }
  2078. static Elf_Addr
  2079. SUFFIX (put_section) (Elf_Shdr *s, int i,
  2080. Elf_Addr current_address,
  2081. struct section_metadata *smd,
  2082. const struct grub_install_image_target_desc *image_target)
  2083. {
  2084. Elf_Word align = grub_host_to_target_addr (s->sh_addralign);
  2085. const char *name = smd->strtab + grub_host_to_target32 (s->sh_name);
  2086. if (align)
  2087. current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
  2088. align)
  2089. - image_target->vaddr_offset;
  2090. grub_util_info ("locating the section %s at 0x%"
  2091. GRUB_HOST_PRIxLONG_LONG,
  2092. name, (unsigned long long) current_address);
  2093. if (!is_relocatable (image_target))
  2094. current_address = grub_host_to_target_addr (s->sh_addr)
  2095. - image_target->link_addr;
  2096. smd->addrs[i] = current_address;
  2097. current_address += grub_host_to_target_addr (s->sh_size);
  2098. return current_address;
  2099. }
  2100. /*
  2101. * Locate section addresses by merging code sections and data sections
  2102. * into .text and .data, respectively.
  2103. */
  2104. static void
  2105. SUFFIX (locate_sections) (Elf_Ehdr *e, const char *kernel_path,
  2106. struct section_metadata *smd,
  2107. struct grub_mkimage_layout *layout,
  2108. const struct grub_install_image_target_desc *image_target)
  2109. {
  2110. int i;
  2111. Elf_Shdr *s;
  2112. layout->align = 1;
  2113. /* Page-aligning simplifies relocation handling. */
  2114. if (image_target->elf_target == EM_AARCH64)
  2115. layout->align = 4096;
  2116. layout->kernel_size = 0;
  2117. for (i = 0, s = smd->sections;
  2118. i < smd->num_sections;
  2119. i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
  2120. if ((grub_target_to_host (s->sh_flags) & SHF_ALLOC)
  2121. && grub_host_to_target32 (s->sh_addralign) > layout->align)
  2122. layout->align = grub_host_to_target32 (s->sh_addralign);
  2123. /* .text */
  2124. for (i = 0, s = smd->sections;
  2125. i < smd->num_sections;
  2126. i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
  2127. if (SUFFIX (is_text_section) (s, image_target))
  2128. {
  2129. layout->kernel_size = SUFFIX (put_section) (s, i, layout->kernel_size,
  2130. smd, image_target);
  2131. if (!is_relocatable (image_target) &&
  2132. grub_host_to_target_addr (s->sh_addr) != image_target->link_addr)
  2133. {
  2134. char *msg
  2135. = grub_xasprintf (_("`%s' is miscompiled: its start address is 0x%llx"
  2136. " instead of 0x%llx: ld.gold bug?"),
  2137. kernel_path,
  2138. (unsigned long long) grub_host_to_target_addr (s->sh_addr),
  2139. (unsigned long long) image_target->link_addr);
  2140. grub_util_error ("%s", msg);
  2141. }
  2142. }
  2143. #ifdef MKIMAGE_ELF32
  2144. if (image_target->elf_target == EM_ARM)
  2145. {
  2146. grub_size_t tramp;
  2147. layout->kernel_size = ALIGN_UP (layout->kernel_size, 16);
  2148. tramp = arm_get_trampoline_size (e, smd->sections, smd->section_entsize,
  2149. smd->num_sections, image_target);
  2150. layout->tramp_off = layout->kernel_size;
  2151. layout->kernel_size += ALIGN_UP (tramp, 16);
  2152. }
  2153. #endif
  2154. layout->kernel_size = ALIGN_UP (layout->kernel_size + image_target->vaddr_offset,
  2155. image_target->section_align)
  2156. - image_target->vaddr_offset;
  2157. layout->exec_size = layout->kernel_size;
  2158. /* .data */
  2159. for (i = 0, s = smd->sections;
  2160. i < smd->num_sections;
  2161. i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
  2162. if (SUFFIX (is_data_section) (s, image_target))
  2163. layout->kernel_size = SUFFIX (put_section) (s, i, layout->kernel_size, smd,
  2164. image_target);
  2165. layout->bss_start = layout->kernel_size;
  2166. layout->end = layout->kernel_size;
  2167. /* .bss */
  2168. for (i = 0, s = smd->sections;
  2169. i < smd->num_sections;
  2170. i++, s = (Elf_Shdr *) ((char *) s + smd->section_entsize))
  2171. {
  2172. if (SUFFIX (is_bss_section) (s, image_target))
  2173. layout->end = SUFFIX (put_section) (s, i, layout->end, smd, image_target);
  2174. /*
  2175. * This must to be in the last time this function passes through the loop.
  2176. */
  2177. smd->vaddrs[i] = smd->addrs[i] + image_target->vaddr_offset;
  2178. }
  2179. layout->end = ALIGN_UP (layout->end + image_target->vaddr_offset,
  2180. image_target->section_align) - image_target->vaddr_offset;
  2181. /* Explicitly initialize BSS
  2182. when producing PE32 to avoid a bug in EFI implementations.
  2183. Platforms other than EFI and U-boot shouldn't have .bss in
  2184. their binaries as we build with -Wl,-Ttext.
  2185. */
  2186. if (image_target->id == IMAGE_EFI || !is_relocatable (image_target))
  2187. layout->kernel_size = layout->end;
  2188. }
  2189. char *
  2190. SUFFIX (grub_mkimage_load_image) (const char *kernel_path,
  2191. size_t total_module_size,
  2192. struct grub_mkimage_layout *layout,
  2193. const struct grub_install_image_target_desc *image_target)
  2194. {
  2195. char *kernel_img, *out_img;
  2196. struct section_metadata smd = { 0, 0, 0, 0, 0, 0, 0 };
  2197. Elf_Ehdr *e;
  2198. int i;
  2199. Elf_Shdr *s;
  2200. Elf_Off section_offset;
  2201. grub_size_t kernel_size;
  2202. grub_memset (layout, 0, sizeof (*layout));
  2203. layout->start_address = 0;
  2204. kernel_size = grub_util_get_image_size (kernel_path);
  2205. kernel_img = xmalloc (kernel_size);
  2206. grub_util_load_image (kernel_path, kernel_img);
  2207. e = (Elf_Ehdr *) kernel_img;
  2208. if (! SUFFIX (check_elf_header) (e, kernel_size, image_target))
  2209. grub_util_error ("invalid ELF header");
  2210. section_offset = grub_target_to_host (e->e_shoff);
  2211. smd.section_entsize = grub_target_to_host16 (e->e_shentsize);
  2212. smd.num_sections = grub_target_to_host16 (e->e_shnum);
  2213. if (kernel_size < section_offset
  2214. + (grub_uint32_t) smd.section_entsize * smd.num_sections)
  2215. grub_util_error (_("premature end of file %s"), kernel_path);
  2216. smd.sections = (Elf_Shdr *) (kernel_img + section_offset);
  2217. /* Relocate sections then symbols in the virtual address space. */
  2218. s = (Elf_Shdr *) ((char *) smd.sections
  2219. + grub_host_to_target16 (e->e_shstrndx) * smd.section_entsize);
  2220. smd.strtab = (char *) e + grub_host_to_target_addr (s->sh_offset);
  2221. smd.addrs = xcalloc (smd.num_sections, sizeof (*smd.addrs));
  2222. smd.vaddrs = xcalloc (smd.num_sections, sizeof (*smd.vaddrs));
  2223. SUFFIX (locate_sections) (e, kernel_path, &smd, layout, image_target);
  2224. if (!is_relocatable (image_target))
  2225. {
  2226. Elf_Addr current_address = layout->kernel_size;
  2227. Elf_Addr bss_start = layout->kernel_size;
  2228. bool is_first = true;
  2229. for (i = 0, s = smd.sections;
  2230. i < smd.num_sections;
  2231. i++, s = (Elf_Shdr *) ((char *) s + smd.section_entsize))
  2232. if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS)
  2233. {
  2234. Elf_Word sec_align = grub_host_to_target_addr (s->sh_addralign);
  2235. const char *name = smd.strtab + grub_host_to_target32 (s->sh_name);
  2236. if (sec_align)
  2237. current_address = ALIGN_UP (current_address
  2238. + image_target->vaddr_offset,
  2239. sec_align)
  2240. - image_target->vaddr_offset;
  2241. grub_util_info ("locating the section %s at 0x%"
  2242. GRUB_HOST_PRIxLONG_LONG,
  2243. name, (unsigned long long) current_address);
  2244. if (!is_relocatable (image_target))
  2245. current_address = grub_host_to_target_addr (s->sh_addr)
  2246. - image_target->link_addr;
  2247. if (is_first == true)
  2248. {
  2249. bss_start = current_address;
  2250. is_first = false;
  2251. }
  2252. smd.vaddrs[i] = current_address
  2253. + image_target->vaddr_offset;
  2254. current_address += grub_host_to_target_addr (s->sh_size);
  2255. }
  2256. current_address = ALIGN_UP (current_address + image_target->vaddr_offset,
  2257. image_target->section_align)
  2258. - image_target->vaddr_offset;
  2259. if (image_target->id == IMAGE_YEELOONG_FLASH
  2260. || image_target->id == IMAGE_FULOONG2F_FLASH
  2261. || image_target->id == IMAGE_LOONGSON_ELF
  2262. || image_target->id == IMAGE_QEMU_MIPS_FLASH
  2263. || image_target->id == IMAGE_MIPS_ARC)
  2264. {
  2265. layout->kernel_size = bss_start;
  2266. }
  2267. layout->bss_size = current_address - layout->kernel_size;
  2268. }
  2269. else
  2270. layout->bss_size = 0;
  2271. if (image_target->id == IMAGE_SPARC64_AOUT
  2272. || image_target->id == IMAGE_SPARC64_RAW
  2273. || image_target->id == IMAGE_UBOOT
  2274. || image_target->id == IMAGE_COREBOOT
  2275. || image_target->id == IMAGE_SPARC64_CDCORE)
  2276. layout->kernel_size = ALIGN_UP (layout->kernel_size, image_target->mod_align);
  2277. if (is_relocatable (image_target))
  2278. {
  2279. smd.symtab = NULL;
  2280. for (i = 0, s = smd.sections;
  2281. i < smd.num_sections;
  2282. i++, s = (Elf_Shdr *) ((char *) s + smd.section_entsize))
  2283. if (s->sh_type == grub_host_to_target32 (SHT_SYMTAB))
  2284. {
  2285. smd.symtab = s;
  2286. break;
  2287. }
  2288. if (! smd.symtab)
  2289. grub_util_error ("%s", _("no symbol table"));
  2290. #ifdef MKIMAGE_ELF64
  2291. if (image_target->elf_target == EM_IA_64)
  2292. {
  2293. grub_size_t tramp;
  2294. layout->kernel_size = ALIGN_UP (layout->kernel_size, 16);
  2295. grub_ia64_dl_get_tramp_got_size (e, &tramp, &layout->got_size);
  2296. layout->tramp_off = layout->kernel_size;
  2297. layout->kernel_size += ALIGN_UP (tramp, 16);
  2298. layout->ia64jmp_off = layout->kernel_size;
  2299. layout->ia64jmpnum = SUFFIX (count_funcs) (e, smd.symtab,
  2300. image_target);
  2301. layout->kernel_size += 16 * layout->ia64jmpnum;
  2302. layout->got_off = layout->kernel_size;
  2303. layout->kernel_size += ALIGN_UP (layout->got_size, 16);
  2304. }
  2305. if (image_target->elf_target == EM_AARCH64)
  2306. {
  2307. grub_size_t tramp;
  2308. layout->kernel_size = ALIGN_UP (layout->kernel_size, 16);
  2309. grub_arm64_dl_get_tramp_got_size (e, &tramp, &layout->got_size);
  2310. layout->got_off = layout->kernel_size;
  2311. layout->kernel_size += ALIGN_UP (layout->got_size, 16);
  2312. }
  2313. #endif
  2314. if (image_target->id == IMAGE_EFI)
  2315. layout->kernel_size = ALIGN_UP (layout->kernel_size,
  2316. GRUB_PE32_FILE_ALIGNMENT);
  2317. }
  2318. else
  2319. {
  2320. layout->reloc_size = 0;
  2321. layout->reloc_section = NULL;
  2322. }
  2323. out_img = xmalloc (layout->kernel_size + total_module_size);
  2324. memset (out_img, 0, layout->kernel_size + total_module_size);
  2325. if (is_relocatable (image_target))
  2326. {
  2327. layout->start_address = SUFFIX (relocate_symbols) (e, &smd,
  2328. (char *) out_img + layout->ia64jmp_off,
  2329. layout->ia64jmp_off + image_target->vaddr_offset,
  2330. layout->bss_start, layout->end, image_target);
  2331. if (layout->start_address == (Elf_Addr) -1)
  2332. grub_util_error ("start symbol is not defined");
  2333. /* Resolve addrs in the virtual address space. */
  2334. SUFFIX (relocate_addrs) (e, &smd, out_img, layout->tramp_off,
  2335. layout->got_off, image_target);
  2336. make_reloc_section (e, layout, &smd, image_target);
  2337. if (image_target->id != IMAGE_EFI)
  2338. {
  2339. out_img = xrealloc (out_img, layout->kernel_size + total_module_size
  2340. + ALIGN_UP (layout->reloc_size, image_target->mod_align));
  2341. memcpy (out_img + layout->kernel_size, layout->reloc_section, layout->reloc_size);
  2342. memset (out_img + layout->kernel_size + layout->reloc_size, 0,
  2343. total_module_size + ALIGN_UP (layout->reloc_size, image_target->mod_align) - layout->reloc_size);
  2344. layout->kernel_size += ALIGN_UP (layout->reloc_size, image_target->mod_align);
  2345. }
  2346. }
  2347. for (i = 0, s = smd.sections;
  2348. i < smd.num_sections;
  2349. i++, s = (Elf_Shdr *) ((char *) s + smd.section_entsize))
  2350. if (SUFFIX (is_kept_section) (s, image_target))
  2351. {
  2352. if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS)
  2353. memset (out_img + smd.addrs[i], 0,
  2354. grub_host_to_target_addr (s->sh_size));
  2355. else
  2356. memcpy (out_img + smd.addrs[i],
  2357. kernel_img + grub_host_to_target_addr (s->sh_offset),
  2358. grub_host_to_target_addr (s->sh_size));
  2359. }
  2360. free (kernel_img);
  2361. free (smd.vaddrs);
  2362. smd.vaddrs = NULL;
  2363. free (smd.addrs);
  2364. smd.addrs = NULL;
  2365. return out_img;
  2366. }