multiboot_mbi2.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705
  1. /*
  2. * GRUB -- GRand Unified Bootloader
  3. * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008,2009 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/machine/memory.h>
  19. #include <grub/memory.h>
  20. #ifdef GRUB_MACHINE_PCBIOS
  21. #include <grub/machine/biosnum.h>
  22. #endif
  23. #include <grub/multiboot.h>
  24. #include <grub/cpu/multiboot.h>
  25. #include <grub/cpu/relocator.h>
  26. #include <grub/disk.h>
  27. #include <grub/device.h>
  28. #include <grub/partition.h>
  29. #include <grub/mm.h>
  30. #include <grub/misc.h>
  31. #include <grub/env.h>
  32. #include <grub/video.h>
  33. #if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_MULTIBOOT) || defined (GRUB_MACHINE_QEMU)
  34. #include <grub/i386/pc/vbe.h>
  35. #define HAS_VGA_TEXT 1
  36. #else
  37. #define HAS_VGA_TEXT 0
  38. #endif
  39. struct module
  40. {
  41. struct module *next;
  42. grub_addr_t start;
  43. grub_size_t size;
  44. char *cmdline;
  45. int cmdline_size;
  46. };
  47. struct module *modules, *modules_last;
  48. static grub_size_t cmdline_size;
  49. static grub_size_t total_modcmd;
  50. static unsigned modcnt;
  51. static char *cmdline = NULL;
  52. static int bootdev_set;
  53. static grub_uint32_t biosdev, slice, part;
  54. grub_err_t
  55. grub_multiboot_load (grub_file_t file)
  56. {
  57. char *buffer;
  58. grub_ssize_t len;
  59. struct multiboot_header *header;
  60. grub_err_t err;
  61. struct multiboot_header_tag *tag;
  62. struct multiboot_header_tag_address *addr_tag = NULL;
  63. int entry_specified = 0;
  64. grub_addr_t entry = 0;
  65. grub_uint32_t console_required = 0;
  66. struct multiboot_header_tag_framebuffer *fbtag = NULL;
  67. int accepted_consoles = GRUB_MULTIBOOT_CONSOLE_EGA_TEXT;
  68. buffer = grub_malloc (MULTIBOOT_SEARCH);
  69. if (!buffer)
  70. return grub_errno;
  71. len = grub_file_read (file, buffer, MULTIBOOT_SEARCH);
  72. if (len < 32)
  73. {
  74. grub_free (buffer);
  75. return grub_error (GRUB_ERR_BAD_OS, "file too small");
  76. }
  77. /* Look for the multiboot header in the buffer. The header should
  78. be at least 12 bytes and aligned on a 4-byte boundary. */
  79. for (header = (struct multiboot_header *) buffer;
  80. ((char *) header <= buffer + len - 12) || (header = 0);
  81. header = (struct multiboot_header *) ((char *) header + MULTIBOOT_HEADER_ALIGN))
  82. {
  83. if (header->magic == MULTIBOOT_HEADER_MAGIC
  84. && !(header->magic + header->architecture
  85. + header->header_length + header->checksum)
  86. && header->architecture == MULTIBOOT_ARCHITECTURE_CURRENT)
  87. break;
  88. }
  89. if (header == 0)
  90. {
  91. grub_free (buffer);
  92. return grub_error (GRUB_ERR_BAD_ARGUMENT, "no multiboot header found");
  93. }
  94. for (tag = (struct multiboot_header_tag *) (header + 1);
  95. tag->type != MULTIBOOT_TAG_TYPE_END;
  96. tag = (struct multiboot_header_tag *) ((char *) tag + tag->size))
  97. switch (tag->type)
  98. {
  99. case MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST:
  100. {
  101. unsigned i;
  102. struct multiboot_header_tag_information_request *request_tag
  103. = (struct multiboot_header_tag_information_request *) tag;
  104. if (request_tag->flags & MULTIBOOT_HEADER_TAG_OPTIONAL)
  105. break;
  106. for (i = 0; i < (request_tag->size - sizeof (request_tag))
  107. / sizeof (request_tag->requests[0]); i++)
  108. switch (request_tag->requests[i])
  109. {
  110. case MULTIBOOT_TAG_TYPE_END:
  111. case MULTIBOOT_TAG_TYPE_CMDLINE:
  112. case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME:
  113. case MULTIBOOT_TAG_TYPE_MODULE:
  114. case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO:
  115. case MULTIBOOT_TAG_TYPE_BOOTDEV:
  116. case MULTIBOOT_TAG_TYPE_MMAP:
  117. case MULTIBOOT_TAG_TYPE_FRAMEBUFFER:
  118. break;
  119. case MULTIBOOT_TAG_TYPE_VBE:
  120. case MULTIBOOT_TAG_TYPE_ELF_SECTIONS:
  121. case MULTIBOOT_TAG_TYPE_APM:
  122. default:
  123. grub_free (buffer);
  124. return grub_error (GRUB_ERR_UNKNOWN_OS,
  125. "unsupported information tag: 0x%x",
  126. request_tag->requests[i]);
  127. }
  128. break;
  129. }
  130. case MULTIBOOT_HEADER_TAG_ADDRESS:
  131. addr_tag = (struct multiboot_header_tag_address *) tag;
  132. break;
  133. case MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS:
  134. entry_specified = 1;
  135. entry = ((struct multiboot_header_tag_entry_address *) tag)->entry_addr;
  136. break;
  137. case MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS:
  138. if (!(((struct multiboot_header_tag_console_flags *) tag)->console_flags
  139. & MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED))
  140. accepted_consoles &= ~GRUB_MULTIBOOT_CONSOLE_EGA_TEXT;
  141. if (((struct multiboot_header_tag_console_flags *) tag)->console_flags
  142. & MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED)
  143. console_required = 1;
  144. break;
  145. case MULTIBOOT_HEADER_TAG_FRAMEBUFFER:
  146. fbtag = (struct multiboot_header_tag_framebuffer *) tag;
  147. accepted_consoles |= GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER;
  148. break;
  149. /* GRUB always page-aligns modules. */
  150. case MULTIBOOT_HEADER_TAG_MODULE_ALIGN:
  151. break;
  152. default:
  153. if (! (tag->flags & MULTIBOOT_HEADER_TAG_OPTIONAL))
  154. {
  155. grub_free (buffer);
  156. return grub_error (GRUB_ERR_UNKNOWN_OS,
  157. "unsupported tag: 0x%x", tag->type);
  158. }
  159. break;
  160. }
  161. if (addr_tag && !entry_specified)
  162. {
  163. grub_free (buffer);
  164. return grub_error (GRUB_ERR_UNKNOWN_OS,
  165. "load address tag without entry address tag");
  166. }
  167. if (addr_tag)
  168. {
  169. int offset = ((char *) header - buffer -
  170. (addr_tag->header_addr - addr_tag->load_addr));
  171. int load_size = ((addr_tag->load_end_addr == 0) ? file->size - offset :
  172. addr_tag->load_end_addr - addr_tag->load_addr);
  173. grub_size_t code_size;
  174. if (addr_tag->bss_end_addr)
  175. code_size = (addr_tag->bss_end_addr - addr_tag->load_addr);
  176. else
  177. code_size = load_size;
  178. grub_multiboot_payload_dest = addr_tag->load_addr;
  179. grub_multiboot_pure_size += code_size;
  180. /* Allocate a bit more to avoid relocations in most cases. */
  181. grub_multiboot_alloc_mbi = grub_multiboot_get_mbi_size () + 65536;
  182. grub_multiboot_payload_orig
  183. = grub_relocator32_alloc (grub_multiboot_pure_size + grub_multiboot_alloc_mbi);
  184. if (! grub_multiboot_payload_orig)
  185. {
  186. grub_free (buffer);
  187. return grub_errno;
  188. }
  189. if ((grub_file_seek (file, offset)) == (grub_off_t) -1)
  190. {
  191. grub_free (buffer);
  192. return grub_errno;
  193. }
  194. grub_file_read (file, (void *) grub_multiboot_payload_orig, load_size);
  195. if (grub_errno)
  196. {
  197. grub_free (buffer);
  198. return grub_errno;
  199. }
  200. if (addr_tag->bss_end_addr)
  201. grub_memset ((void *) (grub_multiboot_payload_orig + load_size), 0,
  202. addr_tag->bss_end_addr - addr_tag->load_addr - load_size);
  203. }
  204. else
  205. {
  206. err = grub_multiboot_load_elf (file, buffer);
  207. if (err)
  208. {
  209. grub_free (buffer);
  210. return err;
  211. }
  212. }
  213. if (entry_specified)
  214. grub_multiboot_payload_eip = entry;
  215. if (fbtag)
  216. err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER,
  217. accepted_consoles,
  218. fbtag->width, fbtag->height,
  219. fbtag->depth, console_required);
  220. else
  221. err = grub_multiboot_set_console (GRUB_MULTIBOOT_CONSOLE_EGA_TEXT,
  222. accepted_consoles,
  223. 0, 0, 0, console_required);
  224. return err;
  225. }
  226. grub_size_t
  227. grub_multiboot_get_mbi_size (void)
  228. {
  229. return 2 * sizeof (grub_uint32_t) + sizeof (struct multiboot_tag)
  230. + (sizeof (struct multiboot_tag_string)
  231. + ALIGN_UP (cmdline_size, MULTIBOOT_TAG_ALIGN))
  232. + (sizeof (struct multiboot_tag_string)
  233. + ALIGN_UP (sizeof (PACKAGE_STRING), MULTIBOOT_TAG_ALIGN))
  234. + (modcnt * sizeof (struct multiboot_tag_module) + total_modcmd)
  235. + sizeof (struct multiboot_tag_basic_meminfo)
  236. + ALIGN_UP (sizeof (struct multiboot_tag_bootdev), MULTIBOOT_TAG_ALIGN)
  237. + (sizeof (struct multiboot_tag_mmap) + grub_get_multiboot_mmap_count ()
  238. * sizeof (struct multiboot_mmap_entry))
  239. + sizeof (struct multiboot_tag_vbe) + MULTIBOOT_TAG_ALIGN - 1;
  240. }
  241. static int
  242. hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type,
  243. void *closure)
  244. {
  245. struct multiboot_mmap_entry **mmap_entry = closure;
  246. (*mmap_entry)->addr = addr;
  247. (*mmap_entry)->len = size;
  248. switch (type)
  249. {
  250. case GRUB_MACHINE_MEMORY_AVAILABLE:
  251. (*mmap_entry)->type = MULTIBOOT_MEMORY_AVAILABLE;
  252. break;
  253. #ifdef GRUB_MACHINE_MEMORY_ACPI_RECLAIMABLE
  254. case GRUB_MACHINE_MEMORY_ACPI_RECLAIMABLE:
  255. (*mmap_entry)->type = MULTIBOOT_MEMORY_ACPI_RECLAIMABLE;
  256. break;
  257. #endif
  258. #ifdef GRUB_MACHINE_MEMORY_NVS
  259. case GRUB_MACHINE_MEMORY_NVS:
  260. (*mmap_entry)->type = MULTIBOOT_MEMORY_NVS;
  261. break;
  262. #endif
  263. default:
  264. (*mmap_entry)->type = MULTIBOOT_MEMORY_RESERVED;
  265. break;
  266. }
  267. (*mmap_entry)++;
  268. return 0;
  269. }
  270. /* Fill previously allocated Multiboot mmap. */
  271. static void
  272. grub_fill_multiboot_mmap (struct multiboot_tag_mmap *tag)
  273. {
  274. struct multiboot_mmap_entry *mmap_entry = tag->entries;
  275. tag->type = MULTIBOOT_TAG_TYPE_MMAP;
  276. tag->size = sizeof (struct multiboot_tag_mmap)
  277. + sizeof (struct multiboot_mmap_entry) * grub_get_multiboot_mmap_count ();
  278. tag->entry_size = sizeof (struct multiboot_mmap_entry);
  279. tag->entry_version = 0;
  280. grub_mmap_iterate (hook, &mmap_entry);
  281. }
  282. static grub_err_t
  283. retrieve_video_parameters (grub_uint8_t **ptrorig)
  284. {
  285. grub_err_t err;
  286. struct grub_video_mode_info mode_info;
  287. void *framebuffer;
  288. grub_video_driver_id_t driv_id;
  289. struct grub_video_palette_data palette[256];
  290. struct multiboot_tag_framebuffer *tag
  291. = (struct multiboot_tag_framebuffer *) *ptrorig;
  292. err = grub_multiboot_set_video_mode ();
  293. if (err)
  294. {
  295. grub_print_error ();
  296. grub_errno = GRUB_ERR_NONE;
  297. }
  298. grub_video_get_palette (0, ARRAY_SIZE (palette), palette);
  299. driv_id = grub_video_get_driver_id ();
  300. #if HAS_VGA_TEXT
  301. if (driv_id == GRUB_VIDEO_DRIVER_NONE)
  302. {
  303. struct grub_vbe_mode_info_block vbe_mode_info;
  304. grub_uint32_t vbe_mode;
  305. #if defined (GRUB_MACHINE_PCBIOS)
  306. {
  307. grub_vbe_status_t status;
  308. void *scratch = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
  309. status = grub_vbe_bios_get_mode (scratch);
  310. vbe_mode = *(grub_uint32_t *) scratch;
  311. if (status != GRUB_VBE_STATUS_OK)
  312. return GRUB_ERR_NONE;
  313. }
  314. #else
  315. vbe_mode = 3;
  316. #endif
  317. /* get_mode_info isn't available for mode 3. */
  318. if (vbe_mode == 3)
  319. {
  320. grub_memset (&vbe_mode_info, 0,
  321. sizeof (struct grub_vbe_mode_info_block));
  322. vbe_mode_info.memory_model = GRUB_VBE_MEMORY_MODEL_TEXT;
  323. vbe_mode_info.x_resolution = 80;
  324. vbe_mode_info.y_resolution = 25;
  325. }
  326. #if defined (GRUB_MACHINE_PCBIOS)
  327. else
  328. {
  329. grub_vbe_status_t status;
  330. void *scratch = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR;
  331. status = grub_vbe_bios_get_mode_info (vbe_mode, scratch);
  332. if (status != GRUB_VBE_STATUS_OK)
  333. return GRUB_ERR_NONE;
  334. grub_memcpy (&vbe_mode_info, scratch,
  335. sizeof (struct grub_vbe_mode_info_block));
  336. }
  337. #endif
  338. if (vbe_mode_info.memory_model == GRUB_VBE_MEMORY_MODEL_TEXT)
  339. {
  340. tag = (struct multiboot_tag_framebuffer *) *ptrorig;
  341. tag->common.type = MULTIBOOT_TAG_TYPE_FRAMEBUFFER;
  342. tag->common.size = 0;
  343. tag->common.framebuffer_addr = 0xb8000;
  344. tag->common.framebuffer_pitch = 2 * vbe_mode_info.x_resolution;
  345. tag->common.framebuffer_width = vbe_mode_info.x_resolution;
  346. tag->common.framebuffer_height = vbe_mode_info.y_resolution;
  347. tag->common.framebuffer_bpp = 16;
  348. tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT;
  349. tag->common.size = sizeof (tag->common);
  350. tag->common.reserved = 0;
  351. *ptrorig += ALIGN_UP (tag->common.size, MULTIBOOT_TAG_ALIGN);
  352. }
  353. return GRUB_ERR_NONE;
  354. }
  355. #else
  356. if (driv_id == GRUB_VIDEO_DRIVER_NONE)
  357. return GRUB_ERR_NONE;
  358. #endif
  359. err = grub_video_get_info_and_fini (&mode_info, &framebuffer);
  360. if (err)
  361. return err;
  362. tag = (struct multiboot_tag_framebuffer *) *ptrorig;
  363. tag->common.type = MULTIBOOT_TAG_TYPE_FRAMEBUFFER;
  364. tag->common.size = 0;
  365. tag->common.framebuffer_addr = (grub_addr_t) framebuffer;
  366. tag->common.framebuffer_pitch = mode_info.pitch;
  367. tag->common.framebuffer_width = mode_info.width;
  368. tag->common.framebuffer_height = mode_info.height;
  369. tag->common.framebuffer_bpp = mode_info.bpp;
  370. tag->common.reserved = 0;
  371. if (mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR)
  372. {
  373. unsigned i;
  374. tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED;
  375. tag->framebuffer_palette_num_colors = mode_info.number_of_colors;
  376. if (tag->framebuffer_palette_num_colors > ARRAY_SIZE (palette))
  377. tag->framebuffer_palette_num_colors = ARRAY_SIZE (palette);
  378. tag->common.size = sizeof (struct multiboot_tag_framebuffer_common)
  379. + sizeof (multiboot_uint16_t) + tag->framebuffer_palette_num_colors
  380. * sizeof (struct multiboot_color);
  381. for (i = 0; i < tag->framebuffer_palette_num_colors; i++)
  382. {
  383. tag->framebuffer_palette[i].red = palette[i].r;
  384. tag->framebuffer_palette[i].green = palette[i].g;
  385. tag->framebuffer_palette[i].blue = palette[i].b;
  386. }
  387. }
  388. else
  389. {
  390. tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_RGB;
  391. tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_RGB;
  392. tag->framebuffer_red_field_position = mode_info.green_field_pos;
  393. tag->framebuffer_red_mask_size = mode_info.green_mask_size;
  394. tag->framebuffer_green_field_position = mode_info.green_field_pos;
  395. tag->framebuffer_green_mask_size = mode_info.green_mask_size;
  396. tag->framebuffer_blue_field_position = mode_info.blue_field_pos;
  397. tag->framebuffer_blue_mask_size = mode_info.blue_mask_size;
  398. tag->common.size = sizeof (struct multiboot_tag_framebuffer_common) + 6;
  399. }
  400. *ptrorig += ALIGN_UP (tag->common.size, MULTIBOOT_TAG_ALIGN);
  401. return GRUB_ERR_NONE;
  402. }
  403. grub_err_t
  404. grub_multiboot_make_mbi (void *orig, grub_uint32_t dest, grub_off_t buf_off,
  405. grub_size_t bufsize)
  406. {
  407. grub_uint8_t *ptrorig;
  408. grub_uint8_t *mbistart = (grub_uint8_t *) orig + buf_off
  409. + (ALIGN_UP (dest + buf_off, MULTIBOOT_TAG_ALIGN) - (dest + buf_off));
  410. grub_err_t err;
  411. if (bufsize < grub_multiboot_get_mbi_size ())
  412. return grub_error (GRUB_ERR_OUT_OF_MEMORY, "mbi buffer is too small");
  413. ptrorig = mbistart + 2 * sizeof (grub_uint32_t);
  414. {
  415. struct multiboot_tag_string *tag = (struct multiboot_tag_string *) ptrorig;
  416. tag->type = MULTIBOOT_TAG_TYPE_CMDLINE;
  417. tag->size = sizeof (struct multiboot_tag_string) + cmdline_size;
  418. grub_memcpy (tag->string, cmdline, cmdline_size);
  419. ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
  420. }
  421. {
  422. struct multiboot_tag_string *tag = (struct multiboot_tag_string *) ptrorig;
  423. tag->type = MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME;
  424. tag->size = sizeof (struct multiboot_tag_string) + sizeof (PACKAGE_STRING);
  425. grub_memcpy (tag->string, PACKAGE_STRING, sizeof (PACKAGE_STRING));
  426. ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
  427. }
  428. {
  429. unsigned i;
  430. struct module *cur;
  431. for (i = 0, cur = modules; i < modcnt; i++, cur = cur->next)
  432. {
  433. struct multiboot_tag_module *tag
  434. = (struct multiboot_tag_module *) ptrorig;
  435. tag->type = MULTIBOOT_TAG_TYPE_MODULE;
  436. tag->size = sizeof (struct multiboot_tag_module) + cur->cmdline_size;
  437. tag->mod_start = dest + cur->start;
  438. tag->mod_end = tag->mod_start + cur->size;
  439. grub_memcpy (tag->cmdline, cur->cmdline, cur->cmdline_size);
  440. ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
  441. }
  442. }
  443. {
  444. struct multiboot_tag_mmap *tag = (struct multiboot_tag_mmap *) ptrorig;
  445. grub_fill_multiboot_mmap (tag);
  446. ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
  447. }
  448. {
  449. struct multiboot_tag_basic_meminfo *tag
  450. = (struct multiboot_tag_basic_meminfo *) ptrorig;
  451. tag->type = MULTIBOOT_TAG_TYPE_BASIC_MEMINFO;
  452. tag->size = sizeof (struct multiboot_tag_basic_meminfo);
  453. /* Convert from bytes to kilobytes. */
  454. tag->mem_lower = grub_mmap_get_lower () / 1024;
  455. tag->mem_upper = grub_mmap_get_upper () / 1024;
  456. ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
  457. }
  458. if (bootdev_set)
  459. {
  460. struct multiboot_tag_bootdev *tag
  461. = (struct multiboot_tag_bootdev *) ptrorig;
  462. tag->type = MULTIBOOT_TAG_TYPE_BOOTDEV;
  463. tag->size = sizeof (struct multiboot_tag_bootdev);
  464. tag->biosdev = biosdev;
  465. tag->slice = slice;
  466. tag->part = part;
  467. ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
  468. }
  469. {
  470. err = retrieve_video_parameters (&ptrorig);
  471. if (err)
  472. {
  473. grub_print_error ();
  474. grub_errno = GRUB_ERR_NONE;
  475. }
  476. }
  477. {
  478. struct multiboot_tag *tag = (struct multiboot_tag *) ptrorig;
  479. tag->type = MULTIBOOT_TAG_TYPE_END;
  480. tag->size = sizeof (struct multiboot_tag);
  481. ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN);
  482. }
  483. ((grub_uint32_t *) mbistart)[0] = ptrorig - mbistart;
  484. ((grub_uint32_t *) mbistart)[1] = 0;
  485. return GRUB_ERR_NONE;
  486. }
  487. void
  488. grub_multiboot_free_mbi (void)
  489. {
  490. struct module *cur, *next;
  491. cmdline_size = 0;
  492. total_modcmd = 0;
  493. modcnt = 0;
  494. grub_free (cmdline);
  495. cmdline = NULL;
  496. bootdev_set = 0;
  497. for (cur = modules; cur; cur = next)
  498. {
  499. next = cur->next;
  500. grub_free (cur->cmdline);
  501. grub_free (cur);
  502. }
  503. modules = NULL;
  504. modules_last = NULL;
  505. }
  506. grub_err_t
  507. grub_multiboot_init_mbi (int argc, char *argv[])
  508. {
  509. grub_ssize_t len = 0;
  510. char *p;
  511. int i;
  512. grub_multiboot_free_mbi ();
  513. for (i = 0; i < argc; i++)
  514. len += grub_strlen (argv[i]) + 1;
  515. if (len == 0)
  516. len = 1;
  517. cmdline = p = grub_malloc (len);
  518. if (! cmdline)
  519. return grub_errno;
  520. cmdline_size = len;
  521. for (i = 0; i < argc; i++)
  522. {
  523. p = grub_stpcpy (p, argv[i]);
  524. *(p++) = ' ';
  525. }
  526. /* Remove the space after the last word. */
  527. if (p != cmdline)
  528. p--;
  529. *p = '\0';
  530. return GRUB_ERR_NONE;
  531. }
  532. grub_err_t
  533. grub_multiboot_add_module (grub_addr_t start, grub_size_t size,
  534. int argc, char *argv[])
  535. {
  536. struct module *newmod;
  537. char *p;
  538. grub_ssize_t len = 0;
  539. int i;
  540. newmod = grub_malloc (sizeof (*newmod));
  541. if (!newmod)
  542. return grub_errno;
  543. newmod->start = start;
  544. newmod->size = size;
  545. for (i = 0; i < argc; i++)
  546. len += grub_strlen (argv[i]) + 1;
  547. if (len == 0)
  548. len = 1;
  549. newmod->cmdline = p = grub_malloc (len);
  550. if (! newmod->cmdline)
  551. {
  552. grub_free (newmod);
  553. return grub_errno;
  554. }
  555. newmod->cmdline_size = len;
  556. total_modcmd += ALIGN_UP (len, MULTIBOOT_TAG_ALIGN);
  557. for (i = 0; i < argc; i++)
  558. {
  559. p = grub_stpcpy (p, argv[i]);
  560. *(p++) = ' ';
  561. }
  562. /* Remove the space after the last word. */
  563. if (p != newmod->cmdline)
  564. p--;
  565. *p = '\0';
  566. if (modules_last)
  567. modules_last->next = newmod;
  568. else
  569. {
  570. modules = newmod;
  571. modules_last->next = NULL;
  572. }
  573. modules_last = newmod;
  574. modcnt++;
  575. return GRUB_ERR_NONE;
  576. }
  577. void
  578. grub_multiboot_set_bootdev (void)
  579. {
  580. grub_device_t dev;
  581. slice = ~0;
  582. part = ~0;
  583. #ifdef GRUB_MACHINE_PCBIOS
  584. biosdev = grub_get_root_biosnumber ();
  585. #else
  586. biosdev = 0xffffffff;
  587. #endif
  588. if (biosdev == 0xffffffff)
  589. return;
  590. dev = grub_device_open (0);
  591. if (dev && dev->disk && dev->disk->partition)
  592. {
  593. if (dev->disk->partition->parent)
  594. {
  595. part = dev->disk->partition->number;
  596. slice = dev->disk->partition->parent->number;
  597. }
  598. else
  599. slice = dev->disk->partition->number;
  600. }
  601. if (dev)
  602. grub_device_close (dev);
  603. bootdev_set = 1;
  604. }