efi_device_path_to_text.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. /*
  2. * EFI device path interface
  3. *
  4. * Copyright (c) 2017 Heinrich Schuchardt
  5. *
  6. * SPDX-License-Identifier: GPL-2.0+
  7. */
  8. #include <common.h>
  9. #include <efi_loader.h>
  10. #define MAC_OUTPUT_LEN 22
  11. #define UNKNOWN_OUTPUT_LEN 23
  12. const efi_guid_t efi_guid_device_path_to_text_protocol =
  13. EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID;
  14. static uint16_t *efi_convert_device_node_to_text(
  15. struct efi_device_path_protocol *device_node,
  16. bool display_only,
  17. bool allow_shortcuts)
  18. {
  19. unsigned long buffer_size;
  20. efi_status_t r;
  21. uint16_t *buffer = NULL;
  22. int i;
  23. switch (device_node->type) {
  24. case DEVICE_PATH_TYPE_END:
  25. return NULL;
  26. case DEVICE_PATH_TYPE_MESSAGING_DEVICE:
  27. switch (device_node->sub_type) {
  28. case DEVICE_PATH_SUB_TYPE_MSG_MAC_ADDR: {
  29. struct efi_device_path_mac_addr *dp =
  30. (struct efi_device_path_mac_addr *)device_node;
  31. if (dp->if_type != 0 && dp->if_type != 1)
  32. break;
  33. r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES,
  34. 2 * MAC_OUTPUT_LEN,
  35. (void **)&buffer);
  36. if (r != EFI_SUCCESS)
  37. return NULL;
  38. sprintf((char *)buffer,
  39. "MAC(%02x%02x%02x%02x%02x%02x,0x%1x)",
  40. dp->mac.addr[0], dp->mac.addr[1],
  41. dp->mac.addr[2], dp->mac.addr[3],
  42. dp->mac.addr[4], dp->mac.addr[5],
  43. dp->if_type);
  44. for (i = MAC_OUTPUT_LEN - 1; i >= 0; --i)
  45. buffer[i] = ((uint8_t *)buffer)[i];
  46. break;
  47. }
  48. }
  49. case DEVICE_PATH_TYPE_MEDIA_DEVICE:
  50. switch (device_node->sub_type) {
  51. case DEVICE_PATH_SUB_TYPE_FILE_PATH:
  52. buffer_size = device_node->length - 4;
  53. r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES,
  54. buffer_size, (void **) &buffer);
  55. if (r != EFI_SUCCESS)
  56. return NULL;
  57. memcpy(buffer, device_node->data, buffer_size);
  58. break;
  59. }
  60. }
  61. /*
  62. * For all node types that we do not yet support return
  63. * 'UNKNOWN(type,subtype)'.
  64. */
  65. if (!buffer) {
  66. r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES,
  67. 2 * UNKNOWN_OUTPUT_LEN,
  68. (void **)&buffer);
  69. if (r != EFI_SUCCESS)
  70. return NULL;
  71. sprintf((char *)buffer,
  72. "UNKNOWN(%04x,%04x)",
  73. device_node->type,
  74. device_node->sub_type);
  75. for (i = UNKNOWN_OUTPUT_LEN - 1; i >= 0; --i)
  76. buffer[i] = ((uint8_t *)buffer)[i];
  77. }
  78. return buffer;
  79. }
  80. static uint16_t EFIAPI *efi_convert_device_node_to_text_ext(
  81. struct efi_device_path_protocol *device_node,
  82. bool display_only,
  83. bool allow_shortcuts)
  84. {
  85. uint16_t *buffer;
  86. EFI_ENTRY("%p, %d, %d", device_node, display_only, allow_shortcuts);
  87. buffer = efi_convert_device_node_to_text(device_node, display_only,
  88. allow_shortcuts);
  89. EFI_EXIT(EFI_SUCCESS);
  90. return buffer;
  91. }
  92. static uint16_t EFIAPI *efi_convert_device_path_to_text(
  93. struct efi_device_path_protocol *device_path,
  94. bool display_only,
  95. bool allow_shortcuts)
  96. {
  97. uint16_t *buffer;
  98. EFI_ENTRY("%p, %d, %d", device_path, display_only, allow_shortcuts);
  99. /*
  100. * Our device paths are all of depth one. So its is sufficient to
  101. * to convert the first node.
  102. */
  103. buffer = efi_convert_device_node_to_text(device_path, display_only,
  104. allow_shortcuts);
  105. EFI_EXIT(EFI_SUCCESS);
  106. return buffer;
  107. }
  108. const struct efi_device_path_to_text_protocol efi_device_path_to_text = {
  109. .convert_device_node_to_text = efi_convert_device_node_to_text_ext,
  110. .convert_device_path_to_text = efi_convert_device_path_to_text,
  111. };