multiboot_mbi2.c 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129
  1. /*
  2. * GRUB -- GRand Unified Bootloader
  3. * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008,2009,2010,2011,2012,2013 Free Software Foundation, Inc.
  4. *
  5. * GRUB is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * GRUB is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include <grub/memory.h>
  19. #ifdef GRUB_MACHINE_PCBIOS
  20. #include <grub/machine/biosnum.h>
  21. #include <grub/machine/apm.h>
  22. #include <grub/machine/memory.h>
  23. #endif
  24. #include <grub/multiboot2.h>
  25. #include <grub/cpu/multiboot.h>
  26. #include <grub/cpu/relocator.h>
  27. #include <grub/disk.h>
  28. #include <grub/device.h>
  29. #include <grub/partition.h>
  30. #include <grub/mm.h>
  31. #include <grub/misc.h>
  32. #include <grub/env.h>
  33. #include <grub/video.h>
  34. #include <grub/acpi.h>
  35. #include <grub/i18n.h>
  36. #include <grub/net.h>
  37. #include <grub/lib/cmdline.h>
  38. #if defined (GRUB_MACHINE_EFI)
  39. #include <grub/efi/efi.h>
  40. #endif
  41. #if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_MULTIBOOT) || defined (GRUB_MACHINE_QEMU)
  42. #include <grub/i386/pc/vbe.h>
  43. #define HAS_VGA_TEXT 1
  44. #else
  45. #define HAS_VGA_TEXT 0
  46. #endif
  47. #if defined (__i386__) || defined (__x86_64__)
  48. #define MBI_MIN_ADDR 0x1000
  49. #else
  50. #define MBI_MIN_ADDR 0
  51. #endif
  52. struct module
  53. {
  54. struct module *next;
  55. grub_addr_t start;
  56. grub_size_t size;
  57. char *cmdline;
  58. int cmdline_size;
  59. };
  60. static struct module *modules, *modules_last;
  61. static grub_size_t cmdline_size;
  62. static grub_size_t total_modcmd;
  63. static unsigned modcnt;
  64. static char *cmdline = NULL;
  65. static int bootdev_set;
  66. static grub_uint32_t biosdev, slice, part;
  67. static grub_size_t elf_sec_num, elf_sec_entsize;
  68. static unsigned elf_sec_shstrndx;
  69. static void *elf_sections;
  70. static int keep_bs = 0;
  71. static grub_uint32_t load_base_addr;
  72. void
  73. grub_multiboot2_add_elfsyms (grub_size_t num, grub_size_t entsize,
  74. unsigned shndx, void *data)
  75. {
  76. elf_sec_num = num;
  77. elf_sec_shstrndx = shndx;
  78. elf_sec_entsize = entsize;
  79. elf_sections = data;
  80. }
  81. static struct multiboot_header *
  82. find_header (grub_properly_aligned_t *buffer, grub_ssize_t len)
  83. {
  84. struct multiboot_header *header;
  85. /* Look for the multiboot header in the buffer. The header should
  86. be at least 12 bytes and aligned on a 4-byte boundary. */
  87. for (header = (struct multiboot_header *) buffer;
  88. ((char *) header <= (char *) buffer + len - 12);
  89. header = (struct multiboot_header *) ((grub_uint32_t *) header + MULTIBOOT_HEADER_ALIGN / 4))
  90. {
  91. if (header->magic == MULTIBOOT2_HEADER_MAGIC
  92. && !(header->magic + header->architecture
  93. + header->header_length + header->checksum)
  94. && header->architecture == MULTIBOOT2_ARCHITECTURE_CURRENT)
  95. return header;
  96. }
  97. return NULL;
  98. }
  99. grub_err_t
  100. grub_multiboot2_load (grub_file_t file, const char *filename)
  101. {
  102. grub_ssize_t len;
  103. struct multiboot_header *header;
  104. grub_err_t err;
  105. struct multiboot_header_tag *tag;
  106. struct multiboot_header_tag_address *addr_tag = NULL;
  107. struct multiboot_header_tag_relocatable *rel_tag;
  108. int entry_specified = 0, efi_entry_specified = 0;
  109. grub_addr_t entry = 0, efi_entry = 0;
  110. grub_uint32_t console_required = 0;
  111. struct multiboot_header_tag_framebuffer *fbtag = NULL;
  112. int accepted_consoles = GRUB_MULTIBOOT2_CONSOLE_EGA_TEXT;
  113. mbi_load_data_t mld;
  114. mld.mbi_ver = 2;
  115. mld.relocatable = 0;
  116. mld.buffer = grub_malloc (MULTIBOOT_SEARCH);
  117. if (!mld.buffer)
  118. return grub_errno;
  119. len = grub_file_read (file, mld.buffer, MULTIBOOT_SEARCH);
  120. if (len < 32)
  121. {
  122. grub_free (mld.buffer);
  123. return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), filename);
  124. }
  125. COMPILE_TIME_ASSERT (MULTIBOOT_HEADER_ALIGN % 4 == 0);
  126. header = find_header (mld.buffer, len);
  127. if (header == 0)
  128. {
  129. grub_free (mld.buffer);
  130. return grub_error (GRUB_ERR_BAD_ARGUMENT, "no multiboot header found");
  131. }
  132. COMPILE_TIME_ASSERT (MULTIBOOT_TAG_ALIGN % 4 == 0);
  133. keep_bs = 0;
  134. for (tag = (struct multiboot_header_tag *) (header + 1);
  135. tag->type != MULTIBOOT_TAG_TYPE_END;
  136. tag = (struct multiboot_header_tag *) ((grub_uint32_t *) tag + ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) / 4))
  137. switch (tag->type)
  138. {
  139. case MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST:
  140. {
  141. unsigned i;
  142. struct multiboot_header_tag_information_request *request_tag
  143. = (struct multiboot_header_tag_information_request *) tag;
  144. if (request_tag->flags & MULTIBOOT_HEADER_TAG_OPTIONAL)
  145. break;
  146. for (i = 0; i < (request_tag->size - sizeof (*request_tag))
  147. / sizeof (request_tag->requests[0]); i++)
  148. switch (request_tag->requests[i])
  149. {
  150. case MULTIBOOT_TAG_TYPE_END:
  151. case MULTIBOOT_TAG_TYPE_CMDLINE:
  152. case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME:
  153. case MULTIBOOT_TAG_TYPE_MODULE:
  154. case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO:
  155. case MULTIBOOT_TAG_TYPE_BOOTDEV:
  156. case MULTIBOOT_TAG_TYPE_MMAP:
  157. case MULTIBOOT_TAG_TYPE_FRAMEBUFFER:
  158. case MULTIBOOT_TAG_TYPE_VBE:
  159. case MULTIBOOT_TAG_TYPE_ELF_SECTIONS:
  160. case MULTIBOOT_TAG_TYPE_APM:
  161. case MULTIBOOT_TAG_TYPE_EFI32:
  162. case MULTIBOOT_TAG_TYPE_EFI64:
  163. case MULTIBOOT_TAG_TYPE_ACPI_OLD:
  164. case MULTIBOOT_TAG_TYPE_ACPI_NEW:
  165. case MULTIBOOT_TAG_TYPE_NETWORK:
  166. case MULTIBOOT_TAG_TYPE_EFI_MMAP:
  167. case MULTIBOOT_TAG_TYPE_EFI_BS:
  168. case MULTIBOOT_TAG_TYPE_EFI32_IH:
  169. case MULTIBOOT_TAG_TYPE_EFI64_IH:
  170. case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR:
  171. break;
  172. default:
  173. grub_free (mld.buffer);
  174. return grub_error (GRUB_ERR_UNKNOWN_OS,
  175. "unsupported information tag: 0x%x",
  176. request_tag->requests[i]);
  177. }
  178. break;
  179. }
  180. case MULTIBOOT_HEADER_TAG_ADDRESS:
  181. addr_tag = (struct multiboot_header_tag_address *) tag;
  182. break;
  183. case MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS:
  184. entry_specified = 1;
  185. entry = ((struct multiboot_header_tag_entry_address *) tag)->entry_addr;
  186. break;
  187. case MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64:
  188. #if defined (GRUB_MACHINE_EFI) && defined (__x86_64__)
  189. efi_entry_specified = 1;
  190. efi_entry = ((struct multiboot_header_tag_entry_address *) tag)->entry_addr;
  191. #endif
  192. break;
  193. case MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS:
  194. if (!(((struct multiboot_header_tag_console_flags *) tag)->console_flags
  195. & MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED))
  196. accepted_consoles &= ~GRUB_MULTIBOOT2_CONSOLE_EGA_TEXT;
  197. if (((struct multiboot_header_tag_console_flags *) tag)->console_flags
  198. & MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED)
  199. console_required = 1;
  200. break;
  201. case MULTIBOOT_HEADER_TAG_FRAMEBUFFER:
  202. fbtag = (struct multiboot_header_tag_framebuffer *) tag;
  203. accepted_consoles |= GRUB_MULTIBOOT2_CONSOLE_FRAMEBUFFER;
  204. break;
  205. case MULTIBOOT_HEADER_TAG_RELOCATABLE:
  206. mld.relocatable = 1;
  207. rel_tag = (struct multiboot_header_tag_relocatable *) tag;
  208. mld.min_addr = rel_tag->min_addr;
  209. mld.max_addr = rel_tag->max_addr;
  210. mld.align = rel_tag->align;
  211. switch (rel_tag->preference)
  212. {
  213. case MULTIBOOT_LOAD_PREFERENCE_LOW:
  214. mld.preference = GRUB_RELOCATOR_PREFERENCE_LOW;
  215. break;
  216. case MULTIBOOT_LOAD_PREFERENCE_HIGH:
  217. mld.preference = GRUB_RELOCATOR_PREFERENCE_HIGH;
  218. break;
  219. default:
  220. mld.preference = GRUB_RELOCATOR_PREFERENCE_NONE;
  221. }
  222. break;
  223. /* GRUB always page-aligns modules. */
  224. case MULTIBOOT_HEADER_TAG_MODULE_ALIGN:
  225. break;
  226. case MULTIBOOT_HEADER_TAG_EFI_BS:
  227. #ifdef GRUB_MACHINE_EFI
  228. keep_bs = 1;
  229. #endif
  230. break;
  231. default:
  232. if (! (tag->flags & MULTIBOOT_HEADER_TAG_OPTIONAL))
  233. {
  234. grub_free (mld.buffer);
  235. return grub_error (GRUB_ERR_UNKNOWN_OS,
  236. "unsupported tag: 0x%x", tag->type);
  237. }
  238. break;
  239. }
  240. if (addr_tag && !entry_specified && !(keep_bs && efi_entry_specified))
  241. {
  242. grub_free (mld.buffer);
  243. return grub_error (GRUB_ERR_UNKNOWN_OS,
  244. "load address tag without entry address tag");
  245. }
  246. if (addr_tag)
  247. {
  248. grub_uint64_t load_addr = (addr_tag->load_addr + 1)
  249. ? addr_tag->load_addr : (addr_tag->header_addr
  250. - ((char *) header - (char *) mld.buffer));
  251. int offset = ((char *) header - (char *) mld.buffer -
  252. (addr_tag->header_addr - load_addr));
  253. int load_size = ((addr_tag->load_end_addr == 0) ? file->size - offset :
  254. addr_tag->load_end_addr - addr_tag->load_addr);
  255. grub_size_t code_size;
  256. void *source;
  257. grub_relocator_chunk_t ch;
  258. if (addr_tag->bss_end_addr)
  259. code_size = (addr_tag->bss_end_addr - load_addr);
  260. else
  261. code_size = load_size;
  262. if (mld.relocatable)
  263. {
  264. if (code_size > mld.max_addr || mld.min_addr > mld.max_addr - code_size)
  265. {
  266. grub_free (mld.buffer);
  267. return grub_error (GRUB_ERR_BAD_OS, "invalid min/max address and/or load size");
  268. }
  269. err = grub_relocator_alloc_chunk_align_safe (grub_multiboot2_relocator, &ch,
  270. mld.min_addr, mld.max_addr,
  271. code_size, mld.align ? mld.align : 1,
  272. mld.preference, keep_bs);
  273. }
  274. else
  275. err = grub_relocator_alloc_chunk_addr (grub_multiboot2_relocator,
  276. &ch, load_addr, code_size);
  277. if (err)
  278. {
  279. grub_dprintf ("multiboot_loader", "Error loading aout kludge\n");
  280. grub_free (mld.buffer);
  281. return err;
  282. }
  283. mld.link_base_addr = load_addr;
  284. mld.load_base_addr = get_physical_target_address (ch);
  285. source = get_virtual_current_address (ch);
  286. grub_dprintf ("multiboot_loader", "link_base_addr=0x%x, load_base_addr=0x%x, "
  287. "load_size=0x%lx, relocatable=%d\n", mld.link_base_addr,
  288. mld.load_base_addr, (long) code_size, mld.relocatable);
  289. if (mld.relocatable)
  290. grub_dprintf ("multiboot_loader", "align=0x%lx, preference=0x%x, avoid_efi_boot_services=%d\n",
  291. (long) mld.align, mld.preference, keep_bs);
  292. if ((grub_file_seek (file, offset)) == (grub_off_t) -1)
  293. {
  294. grub_free (mld.buffer);
  295. return grub_errno;
  296. }
  297. grub_file_read (file, source, load_size);
  298. if (grub_errno)
  299. {
  300. grub_free (mld.buffer);
  301. return grub_errno;
  302. }
  303. if (addr_tag->bss_end_addr)
  304. grub_memset ((grub_uint8_t *) source + load_size, 0,
  305. addr_tag->bss_end_addr - load_addr - load_size);
  306. }
  307. else
  308. {
  309. mld.file = file;
  310. mld.filename = filename;
  311. mld.avoid_efi_boot_services = keep_bs;
  312. err = grub_multiboot2_load_elf (&mld);
  313. if (err)
  314. {
  315. grub_free (mld.buffer);
  316. return err;
  317. }
  318. }
  319. load_base_addr = mld.load_base_addr;
  320. if (keep_bs && efi_entry_specified)
  321. grub_multiboot2_payload_eip = efi_entry;
  322. else if (entry_specified)
  323. grub_multiboot2_payload_eip = entry;
  324. if (mld.relocatable)
  325. {
  326. /*
  327. * Both branches are mathematically equivalent. However, it looks
  328. * that real life (C?) is more complicated. I am trying to avoid
  329. * wrap around here if mld.load_base_addr < mld.link_base_addr.
  330. * If you look at C operator precedence then everything should work.
  331. * However, I am not 100% sure that a given compiler will not
  332. * optimize/break this stuff. So, maybe we should use signed
  333. * 64-bit int here.
  334. */
  335. if (mld.load_base_addr >= mld.link_base_addr)
  336. grub_multiboot2_payload_eip += mld.load_base_addr - mld.link_base_addr;
  337. else
  338. grub_multiboot2_payload_eip -= mld.link_base_addr - mld.load_base_addr;
  339. }
  340. if (fbtag)
  341. err = grub_multiboot2_set_console (GRUB_MULTIBOOT2_CONSOLE_FRAMEBUFFER,
  342. accepted_consoles,
  343. fbtag->width, fbtag->height,
  344. fbtag->depth, console_required);
  345. else
  346. err = grub_multiboot2_set_console (GRUB_MULTIBOOT2_CONSOLE_EGA_TEXT,
  347. accepted_consoles,
  348. 0, 0, 0, console_required);
  349. return err;
  350. }
  351. static grub_size_t
  352. acpiv2_size (void)
  353. {
  354. #if GRUB_MACHINE_HAS_ACPI
  355. struct grub_acpi_rsdp_v20 *p = grub_acpi_get_rsdpv2 ();
  356. if (!p)
  357. return 0;
  358. return ALIGN_UP (sizeof (struct multiboot_tag_old_acpi)
  359. + p->length, MULTIBOOT_TAG_ALIGN);
  360. #else
  361. return 0;
  362. #endif
  363. }
  364. #ifdef GRUB_MACHINE_EFI
  365. static grub_efi_uintn_t efi_mmap_size = 0;
  366. #endif
  367. static grub_size_t
  368. net_size (void)
  369. {
  370. struct grub_net_network_level_interface *net;
  371. grub_size_t ret = 0;
  372. FOR_NET_NETWORK_LEVEL_INTERFACES(net)
  373. if (net->dhcp_ack)
  374. ret += ALIGN_UP (sizeof (struct multiboot_tag_network) + net->dhcp_acklen,
  375. MULTIBOOT_TAG_ALIGN);
  376. return ret;
  377. }
  378. static grub_size_t
  379. grub_multiboot2_get_mbi_size (void)
  380. {
  381. #ifdef GRUB_MACHINE_EFI
  382. if (!keep_bs && !efi_mmap_size)
  383. efi_mmap_size = grub_efi_find_mmap_size ();
  384. #endif
  385. return 2 * sizeof (grub_uint32_t) + sizeof (struct multiboot_tag)
  386. + sizeof (struct multiboot_tag)
  387. + (sizeof (struct multiboot_tag_string)
  388. + ALIGN_UP (cmdline_size, MULTIBOOT_TAG_ALIGN))
  389. + (sizeof (struct multiboot_tag_string)
  390. + ALIGN_UP (sizeof (PACKAGE_STRING), MULTIBOOT_TAG_ALIGN))
  391. + (modcnt * sizeof (struct multiboot_tag_module) + total_modcmd)
  392. + ALIGN_UP (sizeof (struct multiboot_tag_basic_meminfo),
  393. MULTIBOOT_TAG_ALIGN)
  394. + ALIGN_UP (sizeof (struct multiboot_tag_bootdev), MULTIBOOT_TAG_ALIGN)
  395. + ALIGN_UP (sizeof (struct multiboot_tag_elf_sections), MULTIBOOT_TAG_ALIGN)
  396. + ALIGN_UP (elf_sec_entsize * elf_sec_num, MULTIBOOT_TAG_ALIGN)
  397. + ALIGN_UP ((sizeof (struct multiboot_tag_mmap)
  398. + grub_multiboot2_get_mmap_count ()
  399. * sizeof (struct multiboot_mmap_entry)), MULTIBOOT_TAG_ALIGN)
  400. + ALIGN_UP (sizeof (struct multiboot_tag_framebuffer), MULTIBOOT_TAG_ALIGN)
  401. + ALIGN_UP (sizeof (struct multiboot_tag_old_acpi)
  402. + sizeof (struct grub_acpi_rsdp_v10), MULTIBOOT_TAG_ALIGN)
  403. + ALIGN_UP (sizeof (struct multiboot_tag_load_base_addr), MULTIBOOT_TAG_ALIGN)
  404. + acpiv2_size ()
  405. + net_size ()
  406. #ifdef GRUB_MACHINE_EFI
  407. + ALIGN_UP (sizeof (struct multiboot_tag_efi32), MULTIBOOT_TAG_ALIGN)
  408. + ALIGN_UP (sizeof (struct multiboot_tag_efi32_ih), MULTIBOOT_TAG_ALIGN)
  409. + ALIGN_UP (sizeof (struct multiboot_tag_efi64), MULTIBOOT_TAG_ALIGN)
  410. + ALIGN_UP (sizeof (struct multiboot_tag_efi64_ih), MULTIBOOT_TAG_ALIGN)
  411. + ALIGN_UP (sizeof (struct multiboot_tag_efi_mmap)
  412. + efi_mmap_size, MULTIBOOT_TAG_ALIGN)
  413. #endif
  414. + sizeof (struct multiboot_tag_vbe) + MULTIBOOT_TAG_ALIGN - 1
  415. + sizeof (struct multiboot_tag_apm) + MULTIBOOT_TAG_ALIGN - 1;
  416. }
  417. /* Helper for grub_fill_multiboot_mmap. */
  418. static int
  419. grub_fill_multiboot_mmap_iter (grub_uint64_t addr, grub_uint64_t size,
  420. grub_memory_type_t type, void *data)
  421. {
  422. struct multiboot_mmap_entry **mmap_entry = data;
  423. (*mmap_entry)->addr = addr;
  424. (*mmap_entry)->len = size;
  425. (*mmap_entry)->type = type;
  426. (*mmap_entry)->zero = 0;
  427. (*mmap_entry)++;
  428. return 0;
  429. }
  430. /* Fill previously allocated Multiboot mmap. */
  431. static void
  432. grub_fill_multiboot_mmap (struct multiboot_tag_mmap *tag)
  433. {
  434. struct multiboot_mmap_entry *mmap_entry = tag->entries;
  435. tag->type = MULTIBOOT_TAG_TYPE_MMAP;
  436. tag->size = sizeof (struct multiboot_tag_mmap)
  437. + sizeof (struct multiboot_mmap_entry) * grub_multiboot2_get_mmap_count ();
  438. tag->entry_size = sizeof (struct multiboot_mmap_entry);
  439. tag->entry_version = 0;
  440. grub_mmap_iterate (grub_fill_multiboot_mmap_iter, &mmap_entry);
  441. }
  442. #if defined (GRUB_MACHINE_PCBIOS)
  443. static void
  444. fill_vbe_tag (struct multiboot_tag_vbe *tag)
  445. {
  446. grub_vbe_status_t status;
  447. void *scratch = grub_absolute_pointer (GRUB_MEMORY_MACHINE_SCRATCH_ADDR);
  448. tag->type = MULTIBOOT_TAG_TYPE_VBE;
  449. tag->size = 0;
  450. status = grub_vbe_bios_get_controller_info (scratch);
  451. if (status != GRUB_VBE_STATUS_OK)
  452. return;
  453. grub_memcpy (&tag->vbe_control_info, scratch,
  454. sizeof (struct grub_vbe_info_block));
  455. status = grub_vbe_bios_get_mode (scratch);
  456. tag->vbe_mode = *(grub_uint32_t *) scratch;
  457. if (status != GRUB_VBE_STATUS_OK)
  458. return;
  459. /* get_mode_info isn't available for mode 3. */
  460. if (tag->vbe_mode == 3)
  461. {
  462. struct grub_vbe_mode_info_block *mode_info = (void *) &tag->vbe_mode_info;
  463. grub_memset (mode_info, 0,
  464. sizeof (struct grub_vbe_mode_info_block));
  465. mode_info->memory_model = GRUB_VBE_MEMORY_MODEL_TEXT;
  466. mode_info->x_resolution = 80;
  467. mode_info->y_resolution = 25;
  468. }
  469. else
  470. {
  471. status = grub_vbe_bios_get_mode_info (tag->vbe_mode, scratch);
  472. if (status != GRUB_VBE_STATUS_OK)
  473. return;
  474. grub_memcpy (&tag->vbe_mode_info, scratch,
  475. sizeof (struct grub_vbe_mode_info_block));
  476. }
  477. grub_vbe_bios_get_pm_interface (&tag->vbe_interface_seg,
  478. &tag->vbe_interface_off,
  479. &tag->vbe_interface_len);
  480. tag->size = sizeof (*tag);
  481. }
  482. #endif
  483. static grub_err_t
  484. retrieve_video_parameters (grub_properly_aligned_t **ptrorig)
  485. {
  486. grub_err_t err;
  487. struct grub_video_mode_info mode_info;
  488. void *framebuffer;
  489. grub_video_driver_id_t driv_id;
  490. struct grub_video_palette_data palette[256];
  491. struct multiboot_tag_framebuffer *tag
  492. = (struct multiboot_tag_framebuffer *) *ptrorig;
  493. err = grub_multiboot2_set_video_mode ();
  494. if (err)
  495. {
  496. grub_print_error ();
  497. grub_errno = GRUB_ERR_NONE;
  498. }
  499. grub_video_get_palette (0, ARRAY_SIZE (palette), palette);
  500. driv_id = grub_video_get_driver_id ();
  501. #if HAS_VGA_TEXT
  502. if (driv_id == GRUB_VIDEO_DRIVER_NONE)
  503. {
  504. struct grub_vbe_mode_info_block vbe_mode_info;
  505. grub_uint32_t vbe_mode;
  506. #if defined (GRUB_MACHINE_PCBIOS)
  507. {
  508. grub_vbe_status_t status;
  509. void *scratch = grub_absolute_pointer (GRUB_MEMORY_MACHINE_SCRATCH_ADDR);
  510. status = grub_vbe_bios_get_mode (scratch);
  511. vbe_mode = *(grub_uint32_t *) scratch;
  512. if (status != GRUB_VBE_STATUS_OK)
  513. return GRUB_ERR_NONE;
  514. }
  515. #else
  516. vbe_mode = 3;
  517. #endif
  518. /* get_mode_info isn't available for mode 3. */
  519. if (vbe_mode == 3)
  520. {
  521. grub_memset (&vbe_mode_info, 0,
  522. sizeof (struct grub_vbe_mode_info_block));
  523. vbe_mode_info.memory_model = GRUB_VBE_MEMORY_MODEL_TEXT;
  524. vbe_mode_info.x_resolution = 80;
  525. vbe_mode_info.y_resolution = 25;
  526. }
  527. #if defined (GRUB_MACHINE_PCBIOS)
  528. else
  529. {
  530. grub_vbe_status_t status;
  531. void *scratch = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
  532. status = grub_vbe_bios_get_mode_info (vbe_mode, scratch);
  533. if (status != GRUB_VBE_STATUS_OK)
  534. return GRUB_ERR_NONE;
  535. grub_memcpy (&vbe_mode_info, scratch,
  536. sizeof (struct grub_vbe_mode_info_block));
  537. }
  538. #endif
  539. if (vbe_mode_info.memory_model == GRUB_VBE_MEMORY_MODEL_TEXT)
  540. {
  541. tag = (struct multiboot_tag_framebuffer *) *ptrorig;
  542. tag->common.type = MULTIBOOT_TAG_TYPE_FRAMEBUFFER;
  543. tag->common.size = 0;
  544. tag->common.framebuffer_addr = 0xb8000;
  545. tag->common.framebuffer_pitch = 2 * vbe_mode_info.x_resolution;
  546. tag->common.framebuffer_width = vbe_mode_info.x_resolution;
  547. tag->common.framebuffer_height = vbe_mode_info.y_resolution;
  548. tag->common.framebuffer_bpp = 16;
  549. tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT;
  550. tag->common.size = sizeof (tag->common);
  551. tag->common.reserved = 0;
  552. *ptrorig += ALIGN_UP (tag->common.size, MULTIBOOT_TAG_ALIGN)
  553. / sizeof (grub_properly_aligned_t);
  554. }
  555. return GRUB_ERR_NONE;
  556. }
  557. #else
  558. if (driv_id == GRUB_VIDEO_DRIVER_NONE)
  559. return GRUB_ERR_NONE;
  560. #endif
  561. #if GRUB_MACHINE_HAS_VBE
  562. {
  563. struct multiboot_tag_vbe *tag_vbe = (struct multiboot_tag_vbe *) *ptrorig;
  564. fill_vbe_tag (tag_vbe);
  565. *ptrorig += ALIGN_UP (tag_vbe->size, MULTIBOOT_TAG_ALIGN)
  566. / sizeof (grub_properly_aligned_t);
  567. }
  568. #endif
  569. err = grub_video_get_info_and_fini (&mode_info, &framebuffer);
  570. if (err)
  571. return err;
  572. tag = (struct multiboot_tag_framebuffer *) *ptrorig;
  573. tag->common.type = MULTIBOOT_TAG_TYPE_FRAMEBUFFER;
  574. tag->common.size = 0;
  575. tag->common.framebuffer_addr = (grub_addr_t) framebuffer;
  576. tag->common.framebuffer_pitch = mode_info.pitch;
  577. tag->common.framebuffer_width = mode_info.width;
  578. tag->common.framebuffer_height = mode_info.height;
  579. tag->common.framebuffer_bpp = mode_info.bpp;
  580. tag->common.reserved = 0;
  581. if (mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR)
  582. {
  583. unsigned i;
  584. tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED;
  585. tag->framebuffer_palette_num_colors = mode_info.number_of_colors;
  586. if (tag->framebuffer_palette_num_colors > ARRAY_SIZE (palette))
  587. tag->framebuffer_palette_num_colors = ARRAY_SIZE (palette);
  588. tag->common.size = sizeof (struct multiboot_tag_framebuffer_common)
  589. + sizeof (multiboot_uint16_t) + tag->framebuffer_palette_num_colors
  590. * sizeof (struct multiboot_color);
  591. for (i = 0; i < tag->framebuffer_palette_num_colors; i++)
  592. {
  593. tag->framebuffer_palette[i].red = palette[i].r;
  594. tag->framebuffer_palette[i].green = palette[i].g;
  595. tag->framebuffer_palette[i].blue = palette[i].b;
  596. }
  597. }
  598. else
  599. {
  600. tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_RGB;
  601. tag->framebuffer_red_field_position = mode_info.red_field_pos;
  602. tag->framebuffer_red_mask_size = mode_info.red_mask_size;
  603. tag->framebuffer_green_field_position = mode_info.green_field_pos;
  604. tag->framebuffer_green_mask_size = mode_info.green_mask_size;
  605. tag->framebuffer_blue_field_position = mode_info.blue_field_pos;
  606. tag->framebuffer_blue_mask_size = mode_info.blue_mask_size;
  607. tag->common.size = sizeof (struct multiboot_tag_framebuffer_common) + 6;
  608. }
  609. *ptrorig += ALIGN_UP (tag->common.size, MULTIBOOT_TAG_ALIGN)
  610. / sizeof (grub_properly_aligned_t);
  611. return GRUB_ERR_NONE;
  612. }
  613. grub_err_t
  614. grub_multiboot2_make_mbi (grub_uint32_t *target)
  615. {
  616. grub_properly_aligned_t *ptrorig;
  617. grub_properly_aligned_t *mbistart;
  618. grub_err_t err;
  619. grub_size_t bufsize;
  620. grub_relocator_chunk_t ch;
  621. bufsize = grub_multiboot2_get_mbi_size ();
  622. COMPILE_TIME_ASSERT (MULTIBOOT_TAG_ALIGN % sizeof (grub_properly_aligned_t) == 0);
  623. err = grub_relocator_alloc_chunk_align (grub_multiboot2_relocator, &ch,
  624. MBI_MIN_ADDR, UP_TO_TOP32 (bufsize),
  625. bufsize, MULTIBOOT_TAG_ALIGN,
  626. GRUB_RELOCATOR_PREFERENCE_NONE, 1);
  627. if (err)
  628. return err;
  629. ptrorig = get_virtual_current_address (ch);
  630. #if defined (__i386__) || defined (__x86_64__)
  631. *target = get_physical_target_address (ch);
  632. #elif defined (__mips)
  633. *target = get_physical_target_address (ch) | 0x80000000;
  634. #else
  635. #error Please complete this
  636. #endif
  637. mbistart = ptrorig;
  638. COMPILE_TIME_ASSERT ((2 * sizeof (grub_uint32_t))
  639. % sizeof (grub_properly_aligned_t) == 0);
  640. COMPILE_TIME_ASSERT (MULTIBOOT_TAG_ALIGN
  641. % sizeof (grub_properly_aligned_t) == 0);
  642. ptrorig += (2 * sizeof (grub_uint32_t)) / sizeof (grub_properly_aligned_t);
  643. {
  644. struct multiboot_tag_load_base_addr *tag = (struct multiboot_tag_load_base_addr *) ptrorig;
  645. tag->type = MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR;
  646. tag->size = sizeof (struct multiboot_tag_load_base_addr);
  647. tag->load_base_addr = load_base_addr;
  648. ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
  649. / sizeof (grub_properly_aligned_t);
  650. }
  651. {
  652. struct multiboot_tag_string *tag = (struct multiboot_tag_string *) ptrorig;
  653. tag->type = MULTIBOOT_TAG_TYPE_CMDLINE;
  654. tag->size = sizeof (struct multiboot_tag_string) + cmdline_size;
  655. grub_memcpy (tag->string, cmdline, cmdline_size);
  656. ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
  657. / sizeof (grub_properly_aligned_t);
  658. }
  659. {
  660. struct multiboot_tag_string *tag = (struct multiboot_tag_string *) ptrorig;
  661. tag->type = MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME;
  662. tag->size = sizeof (struct multiboot_tag_string) + sizeof (PACKAGE_STRING);
  663. grub_memcpy (tag->string, PACKAGE_STRING, sizeof (PACKAGE_STRING));
  664. ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
  665. / sizeof (grub_properly_aligned_t);
  666. }
  667. #ifdef GRUB_MACHINE_PCBIOS
  668. {
  669. struct grub_apm_info info;
  670. if (grub_apm_get_info (&info))
  671. {
  672. struct multiboot_tag_apm *tag = (struct multiboot_tag_apm *) ptrorig;
  673. tag->type = MULTIBOOT_TAG_TYPE_APM;
  674. tag->size = sizeof (struct multiboot_tag_apm);
  675. tag->cseg = info.cseg;
  676. tag->offset = info.offset;
  677. tag->cseg_16 = info.cseg_16;
  678. tag->dseg = info.dseg;
  679. tag->flags = info.flags;
  680. tag->cseg_len = info.cseg_len;
  681. tag->dseg_len = info.dseg_len;
  682. tag->cseg_16_len = info.cseg_16_len;
  683. tag->version = info.version;
  684. ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
  685. / sizeof (grub_properly_aligned_t);
  686. }
  687. }
  688. #endif
  689. {
  690. unsigned i;
  691. struct module *cur;
  692. for (i = 0, cur = modules; i < modcnt; i++, cur = cur->next)
  693. {
  694. struct multiboot_tag_module *tag
  695. = (struct multiboot_tag_module *) ptrorig;
  696. tag->type = MULTIBOOT_TAG_TYPE_MODULE;
  697. tag->size = sizeof (struct multiboot_tag_module) + cur->cmdline_size;
  698. tag->mod_start = cur->start;
  699. tag->mod_end = tag->mod_start + cur->size;
  700. grub_memcpy (tag->cmdline, cur->cmdline, cur->cmdline_size);
  701. ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
  702. / sizeof (grub_properly_aligned_t);
  703. }
  704. }
  705. if (!keep_bs)
  706. {
  707. struct multiboot_tag_mmap *tag = (struct multiboot_tag_mmap *) ptrorig;
  708. grub_fill_multiboot_mmap (tag);
  709. ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
  710. / sizeof (grub_properly_aligned_t);
  711. }
  712. {
  713. struct multiboot_tag_elf_sections *tag
  714. = (struct multiboot_tag_elf_sections *) ptrorig;
  715. tag->type = MULTIBOOT_TAG_TYPE_ELF_SECTIONS;
  716. tag->size = sizeof (struct multiboot_tag_elf_sections)
  717. + elf_sec_entsize * elf_sec_num;
  718. grub_memcpy (tag->sections, elf_sections, elf_sec_entsize * elf_sec_num);
  719. tag->num = elf_sec_num;
  720. tag->entsize = elf_sec_entsize;
  721. tag->shndx = elf_sec_shstrndx;
  722. ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
  723. / sizeof (grub_properly_aligned_t);
  724. }
  725. if (!keep_bs)
  726. {
  727. struct multiboot_tag_basic_meminfo *tag
  728. = (struct multiboot_tag_basic_meminfo *) ptrorig;
  729. tag->type = MULTIBOOT_TAG_TYPE_BASIC_MEMINFO;
  730. tag->size = sizeof (struct multiboot_tag_basic_meminfo);
  731. /* Convert from bytes to kilobytes. */
  732. tag->mem_lower = grub_mmap_get_lower () / 1024;
  733. tag->mem_upper = grub_mmap_get_upper () / 1024;
  734. ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
  735. / sizeof (grub_properly_aligned_t);
  736. }
  737. {
  738. struct grub_net_network_level_interface *net;
  739. FOR_NET_NETWORK_LEVEL_INTERFACES(net)
  740. if (net->dhcp_ack)
  741. {
  742. struct multiboot_tag_network *tag
  743. = (struct multiboot_tag_network *) ptrorig;
  744. tag->type = MULTIBOOT_TAG_TYPE_NETWORK;
  745. tag->size = sizeof (struct multiboot_tag_network) + net->dhcp_acklen;
  746. grub_memcpy (tag->dhcpack, net->dhcp_ack, net->dhcp_acklen);
  747. ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
  748. / sizeof (grub_properly_aligned_t);
  749. }
  750. }
  751. if (bootdev_set)
  752. {
  753. struct multiboot_tag_bootdev *tag
  754. = (struct multiboot_tag_bootdev *) ptrorig;
  755. tag->type = MULTIBOOT_TAG_TYPE_BOOTDEV;
  756. tag->size = sizeof (struct multiboot_tag_bootdev);
  757. tag->biosdev = biosdev;
  758. tag->slice = slice;
  759. tag->part = part;
  760. ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
  761. / sizeof (grub_properly_aligned_t);
  762. }
  763. {
  764. err = retrieve_video_parameters (&ptrorig);
  765. if (err)
  766. {
  767. grub_print_error ();
  768. grub_errno = GRUB_ERR_NONE;
  769. }
  770. }
  771. #if defined (GRUB_MACHINE_EFI) && defined (__x86_64__)
  772. {
  773. struct multiboot_tag_efi64 *tag = (struct multiboot_tag_efi64 *) ptrorig;
  774. tag->type = MULTIBOOT_TAG_TYPE_EFI64;
  775. tag->size = sizeof (*tag);
  776. tag->pointer = (grub_addr_t) grub_efi_system_table;
  777. ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
  778. / sizeof (grub_properly_aligned_t);
  779. }
  780. #endif
  781. #if defined (GRUB_MACHINE_EFI) && defined (__i386__)
  782. {
  783. struct multiboot_tag_efi32 *tag = (struct multiboot_tag_efi32 *) ptrorig;
  784. tag->type = MULTIBOOT_TAG_TYPE_EFI32;
  785. tag->size = sizeof (*tag);
  786. tag->pointer = (grub_addr_t) grub_efi_system_table;
  787. ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
  788. / sizeof (grub_properly_aligned_t);
  789. }
  790. #endif
  791. #if GRUB_MACHINE_HAS_ACPI
  792. {
  793. struct multiboot_tag_old_acpi *tag = (struct multiboot_tag_old_acpi *)
  794. ptrorig;
  795. struct grub_acpi_rsdp_v10 *a = grub_acpi_get_rsdpv1 ();
  796. if (a)
  797. {
  798. tag->type = MULTIBOOT_TAG_TYPE_ACPI_OLD;
  799. tag->size = sizeof (*tag) + sizeof (*a);
  800. grub_memcpy (tag->rsdp, a, sizeof (*a));
  801. ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
  802. / sizeof (grub_properly_aligned_t);
  803. }
  804. }
  805. {
  806. struct multiboot_tag_new_acpi *tag = (struct multiboot_tag_new_acpi *)
  807. ptrorig;
  808. struct grub_acpi_rsdp_v20 *a = grub_acpi_get_rsdpv2 ();
  809. if (a)
  810. {
  811. tag->type = MULTIBOOT_TAG_TYPE_ACPI_NEW;
  812. tag->size = sizeof (*tag) + a->length;
  813. grub_memcpy (tag->rsdp, a, a->length);
  814. ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
  815. / sizeof (grub_properly_aligned_t);
  816. }
  817. }
  818. #endif
  819. #ifdef GRUB_MACHINE_EFI
  820. {
  821. struct multiboot_tag_efi_mmap *tag = (struct multiboot_tag_efi_mmap *) ptrorig;
  822. grub_efi_uintn_t efi_desc_size;
  823. grub_efi_uint32_t efi_desc_version;
  824. if (!keep_bs)
  825. {
  826. tag->type = MULTIBOOT_TAG_TYPE_EFI_MMAP;
  827. tag->size = sizeof (*tag) + efi_mmap_size;
  828. err = grub_efi_finish_boot_services (&efi_mmap_size, tag->efi_mmap, NULL,
  829. &efi_desc_size, &efi_desc_version);
  830. if (err)
  831. return err;
  832. tag->descr_size = efi_desc_size;
  833. tag->descr_vers = efi_desc_version;
  834. tag->size = sizeof (*tag) + efi_mmap_size;
  835. ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
  836. / sizeof (grub_properly_aligned_t);
  837. }
  838. }
  839. if (keep_bs)
  840. {
  841. {
  842. struct multiboot_tag *tag = (struct multiboot_tag *) ptrorig;
  843. tag->type = MULTIBOOT_TAG_TYPE_EFI_BS;
  844. tag->size = sizeof (struct multiboot_tag);
  845. ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
  846. / sizeof (grub_properly_aligned_t);
  847. }
  848. #ifdef __i386__
  849. {
  850. struct multiboot_tag_efi32_ih *tag = (struct multiboot_tag_efi32_ih *) ptrorig;
  851. tag->type = MULTIBOOT_TAG_TYPE_EFI32_IH;
  852. tag->size = sizeof (struct multiboot_tag_efi32_ih);
  853. tag->pointer = (grub_addr_t) grub_efi_image_handle;
  854. ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
  855. / sizeof (grub_properly_aligned_t);
  856. }
  857. #endif
  858. #ifdef __x86_64__
  859. {
  860. struct multiboot_tag_efi64_ih *tag = (struct multiboot_tag_efi64_ih *) ptrorig;
  861. tag->type = MULTIBOOT_TAG_TYPE_EFI64_IH;
  862. tag->size = sizeof (struct multiboot_tag_efi64_ih);
  863. tag->pointer = (grub_addr_t) grub_efi_image_handle;
  864. ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
  865. / sizeof (grub_properly_aligned_t);
  866. }
  867. #endif
  868. }
  869. #endif
  870. {
  871. struct multiboot_tag *tag = (struct multiboot_tag *) ptrorig;
  872. tag->type = MULTIBOOT_TAG_TYPE_END;
  873. tag->size = sizeof (struct multiboot_tag);
  874. ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN)
  875. / sizeof (grub_properly_aligned_t);
  876. }
  877. ((grub_uint32_t *) mbistart)[0] = (char *) ptrorig - (char *) mbistart;
  878. ((grub_uint32_t *) mbistart)[1] = 0;
  879. return GRUB_ERR_NONE;
  880. }
  881. void
  882. grub_multiboot2_free_mbi (void)
  883. {
  884. struct module *cur, *next;
  885. cmdline_size = 0;
  886. total_modcmd = 0;
  887. modcnt = 0;
  888. grub_free (cmdline);
  889. cmdline = NULL;
  890. bootdev_set = 0;
  891. for (cur = modules; cur; cur = next)
  892. {
  893. next = cur->next;
  894. grub_free (cur->cmdline);
  895. grub_free (cur);
  896. }
  897. modules = NULL;
  898. modules_last = NULL;
  899. }
  900. grub_err_t
  901. grub_multiboot2_init_mbi (int argc, char *argv[])
  902. {
  903. grub_ssize_t len = 0;
  904. grub_multiboot2_free_mbi ();
  905. len = grub_loader_cmdline_size (argc, argv);
  906. cmdline = grub_malloc (len);
  907. if (! cmdline)
  908. return grub_errno;
  909. cmdline_size = len;
  910. return grub_create_loader_cmdline (argc, argv, cmdline, cmdline_size,
  911. GRUB_VERIFY_KERNEL_CMDLINE);
  912. }
  913. grub_err_t
  914. grub_multiboot2_add_module (grub_addr_t start, grub_size_t size,
  915. int argc, char *argv[])
  916. {
  917. struct module *newmod;
  918. grub_size_t len = 0;
  919. grub_err_t err;
  920. newmod = grub_malloc (sizeof (*newmod));
  921. if (!newmod)
  922. return grub_errno;
  923. newmod->start = start;
  924. newmod->size = size;
  925. len = grub_loader_cmdline_size (argc, argv);
  926. newmod->cmdline = grub_malloc (len);
  927. if (! newmod->cmdline)
  928. {
  929. grub_free (newmod);
  930. return grub_errno;
  931. }
  932. newmod->cmdline_size = len;
  933. total_modcmd += ALIGN_UP (len, MULTIBOOT_TAG_ALIGN);
  934. err = grub_create_loader_cmdline (argc, argv, newmod->cmdline,
  935. newmod->cmdline_size, GRUB_VERIFY_MODULE_CMDLINE);
  936. if (err)
  937. {
  938. grub_free (newmod->cmdline);
  939. grub_free (newmod);
  940. return err;
  941. }
  942. if (modules_last)
  943. modules_last->next = newmod;
  944. else
  945. modules = newmod;
  946. modules_last = newmod;
  947. modcnt++;
  948. return GRUB_ERR_NONE;
  949. }
  950. void
  951. grub_multiboot2_set_bootdev (void)
  952. {
  953. grub_device_t dev;
  954. slice = ~0;
  955. part = ~0;
  956. #ifdef GRUB_MACHINE_PCBIOS
  957. biosdev = grub_get_root_biosnumber ();
  958. #else
  959. biosdev = 0xffffffff;
  960. #endif
  961. if (biosdev == 0xffffffff)
  962. return;
  963. dev = grub_device_open (0);
  964. if (dev && dev->disk && dev->disk->partition)
  965. {
  966. if (dev->disk->partition->parent)
  967. {
  968. part = dev->disk->partition->number;
  969. slice = dev->disk->partition->parent->number;
  970. }
  971. else
  972. slice = dev->disk->partition->number;
  973. }
  974. if (dev)
  975. grub_device_close (dev);
  976. bootdev_set = 1;
  977. }