efi.c 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052
  1. /* efi.c - generic EFI support */
  2. /*
  3. * GRUB -- GRand Unified Bootloader
  4. * Copyright (C) 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 <grub/misc.h>
  20. #include <grub/charset.h>
  21. #include <grub/efi/api.h>
  22. #include <grub/efi/efi.h>
  23. #include <grub/efi/console_control.h>
  24. #include <grub/efi/pe32.h>
  25. #include <grub/time.h>
  26. #include <grub/term.h>
  27. #include <grub/kernel.h>
  28. #include <grub/mm.h>
  29. #include <grub/loader.h>
  30. /* The handle of GRUB itself. Filled in by the startup code. */
  31. grub_efi_handle_t grub_efi_image_handle;
  32. /* The pointer to a system table. Filled in by the startup code. */
  33. grub_efi_system_table_t *grub_efi_system_table;
  34. static grub_guid_t console_control_guid = GRUB_EFI_CONSOLE_CONTROL_GUID;
  35. static grub_guid_t loaded_image_guid = GRUB_EFI_LOADED_IMAGE_GUID;
  36. static grub_guid_t device_path_guid = GRUB_EFI_DEVICE_PATH_GUID;
  37. void *
  38. grub_efi_locate_protocol (grub_guid_t *protocol, void *registration)
  39. {
  40. void *interface;
  41. grub_efi_status_t status;
  42. status = grub_efi_system_table->boot_services->locate_protocol (protocol,
  43. registration,
  44. &interface);
  45. if (status != GRUB_EFI_SUCCESS)
  46. return 0;
  47. return interface;
  48. }
  49. /* Return the array of handles which meet the requirement. If successful,
  50. the number of handles is stored in NUM_HANDLES. The array is allocated
  51. from the heap. */
  52. grub_efi_handle_t *
  53. grub_efi_locate_handle (grub_efi_locate_search_type_t search_type,
  54. grub_guid_t *protocol,
  55. void *search_key,
  56. grub_efi_uintn_t *num_handles)
  57. {
  58. grub_efi_boot_services_t *b;
  59. grub_efi_status_t status;
  60. grub_efi_handle_t *buffer;
  61. grub_efi_uintn_t buffer_size = 8 * sizeof (grub_efi_handle_t);
  62. buffer = grub_malloc (buffer_size);
  63. if (! buffer)
  64. return 0;
  65. b = grub_efi_system_table->boot_services;
  66. status = b->locate_handle (search_type, protocol, search_key,
  67. &buffer_size, buffer);
  68. if (status == GRUB_EFI_BUFFER_TOO_SMALL)
  69. {
  70. grub_free (buffer);
  71. buffer = grub_malloc (buffer_size);
  72. if (! buffer)
  73. return 0;
  74. status = b->locate_handle (search_type, protocol, search_key,
  75. &buffer_size, buffer);
  76. }
  77. if (status != GRUB_EFI_SUCCESS)
  78. {
  79. grub_free (buffer);
  80. return 0;
  81. }
  82. *num_handles = buffer_size / sizeof (grub_efi_handle_t);
  83. return buffer;
  84. }
  85. void *
  86. grub_efi_open_protocol (grub_efi_handle_t handle,
  87. grub_guid_t *protocol,
  88. grub_efi_uint32_t attributes)
  89. {
  90. grub_efi_boot_services_t *b;
  91. grub_efi_status_t status;
  92. void *interface;
  93. b = grub_efi_system_table->boot_services;
  94. status = b->open_protocol (handle,
  95. protocol,
  96. &interface,
  97. grub_efi_image_handle,
  98. 0,
  99. attributes);
  100. if (status != GRUB_EFI_SUCCESS)
  101. return 0;
  102. return interface;
  103. }
  104. grub_efi_status_t
  105. grub_efi_close_protocol (grub_efi_handle_t handle, grub_guid_t *protocol)
  106. {
  107. grub_efi_boot_services_t *b = grub_efi_system_table->boot_services;
  108. return b->close_protocol (handle, protocol, grub_efi_image_handle, NULL);
  109. }
  110. int
  111. grub_efi_set_text_mode (int on)
  112. {
  113. grub_efi_console_control_protocol_t *c;
  114. grub_efi_screen_mode_t mode, new_mode;
  115. c = grub_efi_locate_protocol (&console_control_guid, 0);
  116. if (! c)
  117. /* No console control protocol instance available, assume it is
  118. already in text mode. */
  119. return 1;
  120. if (c->get_mode (c, &mode, 0, 0) != GRUB_EFI_SUCCESS)
  121. return 0;
  122. new_mode = on ? GRUB_EFI_SCREEN_TEXT : GRUB_EFI_SCREEN_GRAPHICS;
  123. if (mode != new_mode)
  124. if (c->set_mode (c, new_mode) != GRUB_EFI_SUCCESS)
  125. return 0;
  126. return 1;
  127. }
  128. void
  129. grub_efi_stall (grub_efi_uintn_t microseconds)
  130. {
  131. grub_efi_system_table->boot_services->stall (microseconds);
  132. }
  133. grub_efi_loaded_image_t *
  134. grub_efi_get_loaded_image (grub_efi_handle_t image_handle)
  135. {
  136. return grub_efi_open_protocol (image_handle,
  137. &loaded_image_guid,
  138. GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
  139. }
  140. void
  141. grub_reboot (void)
  142. {
  143. grub_machine_fini (GRUB_LOADER_FLAG_NORETURN |
  144. GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY);
  145. grub_efi_system_table->runtime_services->reset_system (GRUB_EFI_RESET_COLD,
  146. GRUB_EFI_SUCCESS, 0,
  147. NULL);
  148. for (;;) ;
  149. }
  150. void
  151. grub_exit (void)
  152. {
  153. grub_machine_fini (GRUB_LOADER_FLAG_NORETURN);
  154. grub_efi_system_table->boot_services->exit (grub_efi_image_handle,
  155. GRUB_EFI_SUCCESS, 0, 0);
  156. for (;;) ;
  157. }
  158. grub_err_t
  159. grub_efi_set_virtual_address_map (grub_efi_uintn_t memory_map_size,
  160. grub_efi_uintn_t descriptor_size,
  161. grub_efi_uint32_t descriptor_version,
  162. grub_efi_memory_descriptor_t *virtual_map)
  163. {
  164. grub_efi_runtime_services_t *r;
  165. grub_efi_status_t status;
  166. r = grub_efi_system_table->runtime_services;
  167. status = r->set_virtual_address_map (memory_map_size, descriptor_size,
  168. descriptor_version, virtual_map);
  169. if (status == GRUB_EFI_SUCCESS)
  170. return GRUB_ERR_NONE;
  171. return grub_error (GRUB_ERR_IO, "set_virtual_address_map failed");
  172. }
  173. grub_err_t
  174. grub_efi_set_variable_with_attributes (const char *var, const grub_guid_t *guid,
  175. void *data, grub_size_t datasize, grub_efi_uint32_t attributes)
  176. {
  177. grub_efi_status_t status;
  178. grub_efi_runtime_services_t *r;
  179. grub_efi_char16_t *var16;
  180. grub_utf8_to_utf16_alloc (var, &var16, NULL);
  181. if (var16 == NULL)
  182. return grub_errno;
  183. r = grub_efi_system_table->runtime_services;
  184. status = r->set_variable (var16, guid, attributes, datasize, data);
  185. grub_free (var16);
  186. if (status == GRUB_EFI_SUCCESS)
  187. return GRUB_ERR_NONE;
  188. return grub_error (GRUB_ERR_IO, "could not set EFI variable `%s'", var);
  189. }
  190. grub_err_t
  191. grub_efi_set_variable (const char *var, const grub_guid_t *guid,
  192. void *data, grub_size_t datasize)
  193. {
  194. return grub_efi_set_variable_with_attributes (var, guid, data, datasize,
  195. GRUB_EFI_VARIABLE_NON_VOLATILE
  196. | GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS
  197. | GRUB_EFI_VARIABLE_RUNTIME_ACCESS);
  198. }
  199. grub_efi_status_t
  200. grub_efi_get_variable_with_attributes (const char *var,
  201. const grub_guid_t *guid,
  202. grub_size_t *datasize_out,
  203. void **data_out,
  204. grub_efi_uint32_t *attributes)
  205. {
  206. grub_efi_status_t status;
  207. grub_efi_uintn_t datasize = 0;
  208. grub_efi_runtime_services_t *r;
  209. grub_efi_char16_t *var16;
  210. void *data;
  211. *data_out = NULL;
  212. *datasize_out = 0;
  213. grub_utf8_to_utf16_alloc (var, &var16, NULL);
  214. if (var16 == NULL)
  215. return grub_errno;
  216. r = grub_efi_system_table->runtime_services;
  217. status = r->get_variable (var16, guid, NULL, &datasize, NULL);
  218. if (status != GRUB_EFI_BUFFER_TOO_SMALL || !datasize)
  219. {
  220. grub_free (var16);
  221. return status;
  222. }
  223. data = grub_malloc (datasize);
  224. if (!data)
  225. {
  226. grub_free (var16);
  227. return GRUB_EFI_OUT_OF_RESOURCES;
  228. }
  229. status = r->get_variable (var16, guid, attributes, &datasize, data);
  230. grub_free (var16);
  231. if (status == GRUB_EFI_SUCCESS)
  232. {
  233. *data_out = data;
  234. *datasize_out = datasize;
  235. return status;
  236. }
  237. grub_free (data);
  238. return status;
  239. }
  240. grub_err_t
  241. grub_efi_set_variable_to_string (const char *name, const grub_guid_t *guid,
  242. const char *value, grub_efi_uint32_t attributes)
  243. {
  244. grub_efi_char16_t *value_16;
  245. grub_ssize_t len16;
  246. grub_err_t status;
  247. len16 = grub_utf8_to_utf16_alloc (value, &value_16, NULL);
  248. if (len16 < 0)
  249. return grub_errno;
  250. status = grub_efi_set_variable_with_attributes (name, guid,
  251. (void *) value_16, (len16 + 1) * sizeof (value_16[0]),
  252. attributes);
  253. grub_free (value_16);
  254. return status;
  255. }
  256. grub_efi_status_t
  257. grub_efi_get_variable (const char *var, const grub_guid_t *guid,
  258. grub_size_t *datasize_out, void **data_out)
  259. {
  260. return grub_efi_get_variable_with_attributes (var, guid, datasize_out, data_out, NULL);
  261. }
  262. #pragma GCC diagnostic ignored "-Wcast-align"
  263. /* Search the mods section from the PE32/PE32+ image. This code uses
  264. a PE32 header, but should work with PE32+ as well. */
  265. grub_addr_t
  266. grub_efi_section_addr (const char *section_name)
  267. {
  268. grub_efi_loaded_image_t *image;
  269. struct grub_msdos_image_header *header;
  270. struct grub_pe_image_header *pe_image_header;
  271. struct grub_pe32_coff_header *coff_header;
  272. struct grub_pe32_section_table *sections;
  273. struct grub_pe32_section_table *section;
  274. struct grub_module_info *info;
  275. grub_uint16_t i;
  276. image = grub_efi_get_loaded_image (grub_efi_image_handle);
  277. if (! image)
  278. return 0;
  279. header = image->image_base;
  280. pe_image_header
  281. = (struct grub_pe_image_header *) ((char *) header
  282. + header->pe_image_header_offset);
  283. coff_header = &(pe_image_header->coff_header);
  284. sections
  285. = (struct grub_pe32_section_table *) ((char *) coff_header
  286. + sizeof (*coff_header)
  287. + coff_header->optional_header_size);
  288. for (i = 0, section = sections;
  289. i < coff_header->num_sections;
  290. i++, section++)
  291. {
  292. if (grub_strcmp (section->name, section_name) == 0)
  293. break;
  294. }
  295. if (i == coff_header->num_sections)
  296. {
  297. grub_dprintf("sections", "section %d is last section; invalid.\n", i);
  298. return 0;
  299. }
  300. info = (struct grub_module_info *) ((char *) image->image_base
  301. + section->virtual_address);
  302. if (section->name[0] != '.' && info->magic != GRUB_MODULE_MAGIC)
  303. {
  304. grub_dprintf("sections",
  305. "section %d has bad magic %08x, should be %08x\n",
  306. i, info->magic, GRUB_MODULE_MAGIC);
  307. return 0;
  308. }
  309. grub_dprintf("sections", "returning section info for section %d: \"%s\"\n",
  310. i, section->name);
  311. return (grub_addr_t) info;
  312. }
  313. #pragma GCC diagnostic error "-Wcast-align"
  314. char *
  315. grub_efi_get_filename (grub_efi_device_path_t *dp0)
  316. {
  317. char *name = 0, *p, *pi;
  318. grub_size_t filesize = 0;
  319. grub_efi_device_path_t *dp;
  320. if (!dp0)
  321. return NULL;
  322. dp = dp0;
  323. while (dp)
  324. {
  325. grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
  326. grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
  327. if (type == GRUB_EFI_END_DEVICE_PATH_TYPE)
  328. break;
  329. if (type == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE
  330. && subtype == GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE)
  331. {
  332. grub_efi_uint16_t len = GRUB_EFI_DEVICE_PATH_LENGTH (dp);
  333. if (len < 4)
  334. {
  335. grub_error (GRUB_ERR_OUT_OF_RANGE,
  336. "malformed EFI Device Path node has length=%d", len);
  337. return NULL;
  338. }
  339. len = (len - 4) / sizeof (grub_efi_char16_t);
  340. filesize += GRUB_MAX_UTF8_PER_UTF16 * len + 2;
  341. }
  342. dp = GRUB_EFI_NEXT_DEVICE_PATH (dp);
  343. }
  344. if (!filesize)
  345. return NULL;
  346. dp = dp0;
  347. p = name = grub_malloc (filesize);
  348. if (!name)
  349. return NULL;
  350. while (dp)
  351. {
  352. grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
  353. grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
  354. if (type == GRUB_EFI_END_DEVICE_PATH_TYPE)
  355. break;
  356. else if (type == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE
  357. && subtype == GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE)
  358. {
  359. grub_efi_file_path_device_path_t *fp;
  360. grub_efi_uint16_t len;
  361. grub_efi_char16_t *dup_name;
  362. *p++ = '/';
  363. len = GRUB_EFI_DEVICE_PATH_LENGTH (dp);
  364. if (len < 4)
  365. {
  366. grub_error (GRUB_ERR_OUT_OF_RANGE,
  367. "malformed EFI Device Path node has length=%d", len);
  368. grub_free (name);
  369. return NULL;
  370. }
  371. len = (len - 4) / sizeof (grub_efi_char16_t);
  372. fp = (grub_efi_file_path_device_path_t *) dp;
  373. /* According to EFI spec Path Name is NULL terminated */
  374. while (len > 0 && fp->path_name[len - 1] == 0)
  375. len--;
  376. dup_name = grub_calloc (len, sizeof (*dup_name));
  377. if (!dup_name)
  378. {
  379. grub_free (name);
  380. return NULL;
  381. }
  382. p = (char *) grub_utf16_to_utf8 ((unsigned char *) p,
  383. grub_memcpy (dup_name, fp->path_name, len * sizeof (*dup_name)),
  384. len);
  385. grub_free (dup_name);
  386. }
  387. dp = GRUB_EFI_NEXT_DEVICE_PATH (dp);
  388. }
  389. *p = '\0';
  390. for (pi = name, p = name; *pi;)
  391. {
  392. /* EFI breaks paths with backslashes. */
  393. if (*pi == '\\' || *pi == '/')
  394. {
  395. *p++ = '/';
  396. while (*pi == '\\' || *pi == '/')
  397. pi++;
  398. continue;
  399. }
  400. *p++ = *pi++;
  401. }
  402. *p = '\0';
  403. return name;
  404. }
  405. grub_efi_device_path_t *
  406. grub_efi_get_device_path (grub_efi_handle_t handle)
  407. {
  408. return grub_efi_open_protocol (handle, &device_path_guid,
  409. GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
  410. }
  411. /* Return the device path node right before the end node. */
  412. grub_efi_device_path_t *
  413. grub_efi_find_last_device_path (const grub_efi_device_path_t *dp)
  414. {
  415. grub_efi_device_path_t *next, *p;
  416. if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp))
  417. return 0;
  418. for (p = (grub_efi_device_path_t *) dp, next = GRUB_EFI_NEXT_DEVICE_PATH (p);
  419. ! GRUB_EFI_END_ENTIRE_DEVICE_PATH (next);
  420. p = next, next = GRUB_EFI_NEXT_DEVICE_PATH (next))
  421. ;
  422. return p;
  423. }
  424. /* Duplicate a device path. */
  425. grub_efi_device_path_t *
  426. grub_efi_duplicate_device_path (const grub_efi_device_path_t *dp)
  427. {
  428. grub_efi_device_path_t *p;
  429. grub_size_t total_size = 0;
  430. for (p = (grub_efi_device_path_t *) dp;
  431. ;
  432. p = GRUB_EFI_NEXT_DEVICE_PATH (p))
  433. {
  434. grub_size_t len = GRUB_EFI_DEVICE_PATH_LENGTH (p);
  435. /*
  436. * In the event that we find a node that's completely garbage, for
  437. * example if we get to 0x7f 0x01 0x02 0x00 ... (EndInstance with a size
  438. * of 2), GRUB_EFI_END_ENTIRE_DEVICE_PATH() will be true and
  439. * GRUB_EFI_NEXT_DEVICE_PATH() will return NULL, so we won't continue,
  440. * and neither should our consumers, but there won't be any error raised
  441. * even though the device path is junk.
  442. *
  443. * This keeps us from passing junk down back to our caller.
  444. */
  445. if (len < 4)
  446. {
  447. grub_error (GRUB_ERR_OUT_OF_RANGE,
  448. "malformed EFI Device Path node has length=%" PRIuGRUB_SIZE, len);
  449. return NULL;
  450. }
  451. total_size += len;
  452. if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (p))
  453. break;
  454. }
  455. p = grub_malloc (total_size);
  456. if (! p)
  457. return 0;
  458. grub_memcpy (p, dp, total_size);
  459. return p;
  460. }
  461. static void
  462. dump_vendor_path (const char *type, grub_efi_vendor_device_path_t *vendor)
  463. {
  464. grub_uint32_t vendor_data_len = vendor->header.length - sizeof (*vendor);
  465. grub_printf ("/%sVendor(%pG)[%x: ", type, &vendor->vendor_guid, vendor_data_len);
  466. if (vendor->header.length > sizeof (*vendor))
  467. {
  468. grub_uint32_t i;
  469. for (i = 0; i < vendor_data_len; i++)
  470. grub_printf ("%02x ", vendor->vendor_defined_data[i]);
  471. }
  472. grub_printf ("]");
  473. }
  474. /* Print the chain of Device Path nodes. This is mainly for debugging. */
  475. void
  476. grub_efi_print_device_path (grub_efi_device_path_t *dp)
  477. {
  478. while (GRUB_EFI_DEVICE_PATH_VALID (dp))
  479. {
  480. grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp);
  481. grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp);
  482. grub_efi_uint16_t len = GRUB_EFI_DEVICE_PATH_LENGTH (dp);
  483. switch (type)
  484. {
  485. case GRUB_EFI_END_DEVICE_PATH_TYPE:
  486. switch (subtype)
  487. {
  488. case GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE:
  489. grub_printf ("/EndEntire\n");
  490. //grub_putchar ('\n');
  491. break;
  492. case GRUB_EFI_END_THIS_DEVICE_PATH_SUBTYPE:
  493. grub_printf ("/EndThis\n");
  494. //grub_putchar ('\n');
  495. break;
  496. default:
  497. grub_printf ("/EndUnknown(%x)\n", (unsigned) subtype);
  498. break;
  499. }
  500. break;
  501. case GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE:
  502. switch (subtype)
  503. {
  504. case GRUB_EFI_PCI_DEVICE_PATH_SUBTYPE:
  505. {
  506. grub_efi_pci_device_path_t *pci
  507. = (grub_efi_pci_device_path_t *) dp;
  508. grub_printf ("/PCI(%x,%x)",
  509. (unsigned) pci->function, (unsigned) pci->device);
  510. }
  511. break;
  512. case GRUB_EFI_PCCARD_DEVICE_PATH_SUBTYPE:
  513. {
  514. grub_efi_pccard_device_path_t *pccard
  515. = (grub_efi_pccard_device_path_t *) dp;
  516. grub_printf ("/PCCARD(%x)",
  517. (unsigned) pccard->function);
  518. }
  519. break;
  520. case GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE:
  521. {
  522. grub_efi_memory_mapped_device_path_t *mmapped
  523. = (grub_efi_memory_mapped_device_path_t *) dp;
  524. grub_printf ("/MMap(%x,%llx,%llx)",
  525. (unsigned) mmapped->memory_type,
  526. (unsigned long long) mmapped->start_address,
  527. (unsigned long long) mmapped->end_address);
  528. }
  529. break;
  530. case GRUB_EFI_VENDOR_DEVICE_PATH_SUBTYPE:
  531. dump_vendor_path ("Hardware",
  532. (grub_efi_vendor_device_path_t *) dp);
  533. break;
  534. case GRUB_EFI_CONTROLLER_DEVICE_PATH_SUBTYPE:
  535. {
  536. grub_efi_controller_device_path_t *controller
  537. = (grub_efi_controller_device_path_t *) dp;
  538. grub_printf ("/Ctrl(%x)",
  539. (unsigned) controller->controller_number);
  540. }
  541. break;
  542. default:
  543. grub_printf ("/UnknownHW(%x)", (unsigned) subtype);
  544. break;
  545. }
  546. break;
  547. case GRUB_EFI_ACPI_DEVICE_PATH_TYPE:
  548. switch (subtype)
  549. {
  550. case GRUB_EFI_ACPI_DEVICE_PATH_SUBTYPE:
  551. {
  552. grub_efi_acpi_device_path_t *acpi
  553. = (grub_efi_acpi_device_path_t *) dp;
  554. grub_printf ("/ACPI(%x,%x)",
  555. (unsigned) acpi->hid,
  556. (unsigned) acpi->uid);
  557. }
  558. break;
  559. case GRUB_EFI_EXPANDED_ACPI_DEVICE_PATH_SUBTYPE:
  560. {
  561. grub_efi_expanded_acpi_device_path_t *eacpi
  562. = (grub_efi_expanded_acpi_device_path_t *) dp;
  563. grub_printf ("/ACPI(");
  564. if (GRUB_EFI_EXPANDED_ACPI_HIDSTR (dp)[0] == '\0')
  565. grub_printf ("%x,", (unsigned) eacpi->hid);
  566. else
  567. grub_printf ("%s,", GRUB_EFI_EXPANDED_ACPI_HIDSTR (dp));
  568. if (GRUB_EFI_EXPANDED_ACPI_UIDSTR (dp)[0] == '\0')
  569. grub_printf ("%x,", (unsigned) eacpi->uid);
  570. else
  571. grub_printf ("%s,", GRUB_EFI_EXPANDED_ACPI_UIDSTR (dp));
  572. if (GRUB_EFI_EXPANDED_ACPI_CIDSTR (dp)[0] == '\0')
  573. grub_printf ("%x)", (unsigned) eacpi->cid);
  574. else
  575. grub_printf ("%s)", GRUB_EFI_EXPANDED_ACPI_CIDSTR (dp));
  576. }
  577. break;
  578. default:
  579. grub_printf ("/UnknownACPI(%x)", (unsigned) subtype);
  580. break;
  581. }
  582. break;
  583. case GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE:
  584. switch (subtype)
  585. {
  586. case GRUB_EFI_ATAPI_DEVICE_PATH_SUBTYPE:
  587. {
  588. grub_efi_atapi_device_path_t *atapi
  589. = (grub_efi_atapi_device_path_t *) dp;
  590. grub_printf ("/ATAPI(%x,%x,%x)",
  591. (unsigned) atapi->primary_secondary,
  592. (unsigned) atapi->slave_master,
  593. (unsigned) atapi->lun);
  594. }
  595. break;
  596. case GRUB_EFI_SCSI_DEVICE_PATH_SUBTYPE:
  597. {
  598. grub_efi_scsi_device_path_t *scsi
  599. = (grub_efi_scsi_device_path_t *) dp;
  600. grub_printf ("/SCSI(%x,%x)",
  601. (unsigned) scsi->pun,
  602. (unsigned) scsi->lun);
  603. }
  604. break;
  605. case GRUB_EFI_FIBRE_CHANNEL_DEVICE_PATH_SUBTYPE:
  606. {
  607. grub_efi_fibre_channel_device_path_t *fc
  608. = (grub_efi_fibre_channel_device_path_t *) dp;
  609. grub_printf ("/FibreChannel(%llx,%llx)",
  610. (unsigned long long) fc->wwn,
  611. (unsigned long long) fc->lun);
  612. }
  613. break;
  614. case GRUB_EFI_1394_DEVICE_PATH_SUBTYPE:
  615. {
  616. grub_efi_1394_device_path_t *firewire
  617. = (grub_efi_1394_device_path_t *) dp;
  618. grub_printf ("/1394(%llx)",
  619. (unsigned long long) firewire->guid);
  620. }
  621. break;
  622. case GRUB_EFI_USB_DEVICE_PATH_SUBTYPE:
  623. {
  624. grub_efi_usb_device_path_t *usb
  625. = (grub_efi_usb_device_path_t *) dp;
  626. grub_printf ("/USB(%x,%x)",
  627. (unsigned) usb->parent_port_number,
  628. (unsigned) usb->usb_interface);
  629. }
  630. break;
  631. case GRUB_EFI_USB_CLASS_DEVICE_PATH_SUBTYPE:
  632. {
  633. grub_efi_usb_class_device_path_t *usb_class
  634. = (grub_efi_usb_class_device_path_t *) dp;
  635. grub_printf ("/USBClass(%x,%x,%x,%x,%x)",
  636. (unsigned) usb_class->vendor_id,
  637. (unsigned) usb_class->product_id,
  638. (unsigned) usb_class->device_class,
  639. (unsigned) usb_class->device_subclass,
  640. (unsigned) usb_class->device_protocol);
  641. }
  642. break;
  643. case GRUB_EFI_I2O_DEVICE_PATH_SUBTYPE:
  644. {
  645. grub_efi_i2o_device_path_t *i2o
  646. = (grub_efi_i2o_device_path_t *) dp;
  647. grub_printf ("/I2O(%x)", (unsigned) i2o->tid);
  648. }
  649. break;
  650. case GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE:
  651. {
  652. grub_efi_mac_address_device_path_t *mac
  653. = (grub_efi_mac_address_device_path_t *) dp;
  654. grub_printf ("/MacAddr(%02x:%02x:%02x:%02x:%02x:%02x,%x)",
  655. (unsigned) mac->mac_address[0],
  656. (unsigned) mac->mac_address[1],
  657. (unsigned) mac->mac_address[2],
  658. (unsigned) mac->mac_address[3],
  659. (unsigned) mac->mac_address[4],
  660. (unsigned) mac->mac_address[5],
  661. (unsigned) mac->if_type);
  662. }
  663. break;
  664. case GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE:
  665. {
  666. grub_efi_ipv4_device_path_t *ipv4
  667. = (grub_efi_ipv4_device_path_t *) dp;
  668. grub_printf ("/IPv4(%u.%u.%u.%u,%u.%u.%u.%u,%u,%u,%x,%x)",
  669. (unsigned) ipv4->local_ip_address[0],
  670. (unsigned) ipv4->local_ip_address[1],
  671. (unsigned) ipv4->local_ip_address[2],
  672. (unsigned) ipv4->local_ip_address[3],
  673. (unsigned) ipv4->remote_ip_address[0],
  674. (unsigned) ipv4->remote_ip_address[1],
  675. (unsigned) ipv4->remote_ip_address[2],
  676. (unsigned) ipv4->remote_ip_address[3],
  677. (unsigned) ipv4->local_port,
  678. (unsigned) ipv4->remote_port,
  679. (unsigned) ipv4->protocol,
  680. (unsigned) ipv4->static_ip_address);
  681. }
  682. break;
  683. case GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE:
  684. {
  685. grub_efi_ipv6_device_path_t *ipv6
  686. = (grub_efi_ipv6_device_path_t *) dp;
  687. grub_printf ("/IPv6(%x:%x:%x:%x:%x:%x:%x:%x,%x:%x:%x:%x:%x:%x:%x:%x,%u,%u,%x,%x)",
  688. (unsigned) ipv6->local_ip_address[0],
  689. (unsigned) ipv6->local_ip_address[1],
  690. (unsigned) ipv6->local_ip_address[2],
  691. (unsigned) ipv6->local_ip_address[3],
  692. (unsigned) ipv6->local_ip_address[4],
  693. (unsigned) ipv6->local_ip_address[5],
  694. (unsigned) ipv6->local_ip_address[6],
  695. (unsigned) ipv6->local_ip_address[7],
  696. (unsigned) ipv6->remote_ip_address[0],
  697. (unsigned) ipv6->remote_ip_address[1],
  698. (unsigned) ipv6->remote_ip_address[2],
  699. (unsigned) ipv6->remote_ip_address[3],
  700. (unsigned) ipv6->remote_ip_address[4],
  701. (unsigned) ipv6->remote_ip_address[5],
  702. (unsigned) ipv6->remote_ip_address[6],
  703. (unsigned) ipv6->remote_ip_address[7],
  704. (unsigned) ipv6->local_port,
  705. (unsigned) ipv6->remote_port,
  706. (unsigned) ipv6->protocol,
  707. (unsigned) ipv6->static_ip_address);
  708. }
  709. break;
  710. case GRUB_EFI_INFINIBAND_DEVICE_PATH_SUBTYPE:
  711. {
  712. grub_efi_infiniband_device_path_t *ib
  713. = (grub_efi_infiniband_device_path_t *) dp;
  714. grub_printf ("/InfiniBand(%x,%llx,%llx,%llx)",
  715. (unsigned) ib->port_gid[0], /* XXX */
  716. (unsigned long long) ib->remote_id,
  717. (unsigned long long) ib->target_port_id,
  718. (unsigned long long) ib->device_id);
  719. }
  720. break;
  721. case GRUB_EFI_UART_DEVICE_PATH_SUBTYPE:
  722. {
  723. grub_efi_uart_device_path_t *uart
  724. = (grub_efi_uart_device_path_t *) dp;
  725. grub_printf ("/UART(%llu,%u,%x,%x)",
  726. (unsigned long long) uart->baud_rate,
  727. uart->data_bits,
  728. uart->parity,
  729. uart->stop_bits);
  730. }
  731. break;
  732. case GRUB_EFI_SATA_DEVICE_PATH_SUBTYPE:
  733. {
  734. grub_efi_sata_device_path_t *sata;
  735. sata = (grub_efi_sata_device_path_t *) dp;
  736. grub_printf ("/Sata(%x,%x,%x)",
  737. sata->hba_port,
  738. sata->multiplier_port,
  739. sata->lun);
  740. }
  741. break;
  742. case GRUB_EFI_VLAN_DEVICE_PATH_SUBTYPE:
  743. {
  744. grub_efi_vlan_device_path_t *vlan;
  745. vlan = (grub_efi_vlan_device_path_t *) dp;
  746. grub_printf ("/Vlan(%u)", vlan->vlan_id);
  747. }
  748. break;
  749. case GRUB_EFI_VENDOR_MESSAGING_DEVICE_PATH_SUBTYPE:
  750. dump_vendor_path ("Messaging",
  751. (grub_efi_vendor_device_path_t *) dp);
  752. break;
  753. default:
  754. grub_printf ("/UnknownMessaging(%x)", (unsigned) subtype);
  755. break;
  756. }
  757. break;
  758. case GRUB_EFI_MEDIA_DEVICE_PATH_TYPE:
  759. switch (subtype)
  760. {
  761. case GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE:
  762. {
  763. grub_efi_hard_drive_device_path_t *hd = (grub_efi_hard_drive_device_path_t *) dp;
  764. grub_printf ("/HD(%u,%llx,%llx,%02x%02x%02x%02x%02x%02x%02x%02x,%x,%x)",
  765. hd->partition_number,
  766. (unsigned long long) hd->partition_start,
  767. (unsigned long long) hd->partition_size,
  768. (unsigned) hd->partition_signature[0],
  769. (unsigned) hd->partition_signature[1],
  770. (unsigned) hd->partition_signature[2],
  771. (unsigned) hd->partition_signature[3],
  772. (unsigned) hd->partition_signature[4],
  773. (unsigned) hd->partition_signature[5],
  774. (unsigned) hd->partition_signature[6],
  775. (unsigned) hd->partition_signature[7],
  776. (unsigned) hd->partmap_type,
  777. (unsigned) hd->signature_type);
  778. }
  779. break;
  780. case GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE:
  781. {
  782. grub_efi_cdrom_device_path_t *cd
  783. = (grub_efi_cdrom_device_path_t *) dp;
  784. grub_printf ("/CD(%u,%llx,%llx)",
  785. cd->boot_entry,
  786. (unsigned long long) cd->partition_start,
  787. (unsigned long long) cd->partition_size);
  788. }
  789. break;
  790. case GRUB_EFI_VENDOR_MEDIA_DEVICE_PATH_SUBTYPE:
  791. dump_vendor_path ("Media",
  792. (grub_efi_vendor_device_path_t *) dp);
  793. break;
  794. case GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE:
  795. {
  796. grub_efi_file_path_device_path_t *fp;
  797. grub_uint8_t *buf;
  798. fp = (grub_efi_file_path_device_path_t *) dp;
  799. buf = grub_malloc ((len - 4) * 2 + 1);
  800. if (buf)
  801. {
  802. grub_efi_char16_t *dup_name = grub_malloc (len - 4);
  803. if (!dup_name)
  804. {
  805. grub_errno = GRUB_ERR_NONE;
  806. grub_printf ("/File((null))");
  807. grub_free (buf);
  808. break;
  809. }
  810. *grub_utf16_to_utf8 (buf, grub_memcpy (dup_name, fp->path_name, len - 4),
  811. (len - 4) / sizeof (grub_efi_char16_t))
  812. = '\0';
  813. grub_free (dup_name);
  814. }
  815. else
  816. grub_errno = GRUB_ERR_NONE;
  817. grub_printf ("/File(%s)", buf);
  818. grub_free (buf);
  819. }
  820. break;
  821. case GRUB_EFI_PROTOCOL_DEVICE_PATH_SUBTYPE:
  822. {
  823. grub_efi_protocol_device_path_t *proto
  824. = (grub_efi_protocol_device_path_t *) dp;
  825. grub_printf ("/Protocol(%pG)",&proto->guid);
  826. }
  827. break;
  828. default:
  829. grub_printf ("/UnknownMedia(%x)", (unsigned) subtype);
  830. break;
  831. }
  832. break;
  833. case GRUB_EFI_BIOS_DEVICE_PATH_TYPE:
  834. switch (subtype)
  835. {
  836. case GRUB_EFI_BIOS_DEVICE_PATH_SUBTYPE:
  837. {
  838. grub_efi_bios_device_path_t *bios
  839. = (grub_efi_bios_device_path_t *) dp;
  840. grub_printf ("/BIOS(%x,%x,%s)",
  841. (unsigned) bios->device_type,
  842. (unsigned) bios->status_flags,
  843. (char *) (dp + 1));
  844. }
  845. break;
  846. default:
  847. grub_printf ("/UnknownBIOS(%x)", (unsigned) subtype);
  848. break;
  849. }
  850. break;
  851. default:
  852. grub_printf ("/UnknownType(%x,%x)\n",
  853. (unsigned) type,
  854. (unsigned) subtype);
  855. return;
  856. break;
  857. }
  858. if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp))
  859. break;
  860. dp = (grub_efi_device_path_t *) ((char *) dp + len);
  861. }
  862. }
  863. /* Compare device paths. */
  864. int
  865. grub_efi_compare_device_paths (const grub_efi_device_path_t *dp1,
  866. const grub_efi_device_path_t *dp2)
  867. {
  868. if (! dp1 || ! dp2)
  869. /* Return non-zero. */
  870. return 1;
  871. if (dp1 == dp2)
  872. return 0;
  873. while (GRUB_EFI_DEVICE_PATH_VALID (dp1) && GRUB_EFI_DEVICE_PATH_VALID (dp2))
  874. {
  875. grub_efi_uint8_t type1, type2;
  876. grub_efi_uint8_t subtype1, subtype2;
  877. grub_efi_uint16_t len1, len2;
  878. int ret;
  879. type1 = GRUB_EFI_DEVICE_PATH_TYPE (dp1);
  880. type2 = GRUB_EFI_DEVICE_PATH_TYPE (dp2);
  881. if (type1 != type2)
  882. return (int) type2 - (int) type1;
  883. subtype1 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp1);
  884. subtype2 = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp2);
  885. if (subtype1 != subtype2)
  886. return (int) subtype1 - (int) subtype2;
  887. len1 = GRUB_EFI_DEVICE_PATH_LENGTH (dp1);
  888. len2 = GRUB_EFI_DEVICE_PATH_LENGTH (dp2);
  889. if (len1 != len2)
  890. return (int) len1 - (int) len2;
  891. ret = grub_memcmp (dp1, dp2, len1);
  892. if (ret != 0)
  893. return ret;
  894. if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp1))
  895. break;
  896. dp1 = (grub_efi_device_path_t *) ((char *) dp1 + len1);
  897. dp2 = (grub_efi_device_path_t *) ((char *) dp2 + len2);
  898. }
  899. /*
  900. * There's no "right" answer here, but we probably don't want to call a valid
  901. * dp and an invalid dp equal, so pick one way or the other.
  902. */
  903. if (GRUB_EFI_DEVICE_PATH_VALID (dp1) && !GRUB_EFI_DEVICE_PATH_VALID (dp2))
  904. return 1;
  905. else if (!GRUB_EFI_DEVICE_PATH_VALID (dp1) && GRUB_EFI_DEVICE_PATH_VALID (dp2))
  906. return -1;
  907. return 0;
  908. }
  909. void *
  910. grub_efi_find_configuration_table (const grub_guid_t *target_guid)
  911. {
  912. unsigned i;
  913. for (i = 0; i < grub_efi_system_table->num_table_entries; i++)
  914. {
  915. grub_packed_guid_t *guid =
  916. &grub_efi_system_table->configuration_table[i].vendor_guid;
  917. if (! grub_memcmp (guid, target_guid, sizeof (grub_guid_t)))
  918. return (void *)
  919. grub_efi_system_table->configuration_table[i].vendor_table;
  920. }
  921. return 0;
  922. }