efi_device_path_to_text.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  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. break;
  50. case DEVICE_PATH_TYPE_MEDIA_DEVICE:
  51. switch (device_node->sub_type) {
  52. case DEVICE_PATH_SUB_TYPE_FILE_PATH:
  53. buffer_size = device_node->length - 4;
  54. r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES,
  55. buffer_size, (void **) &buffer);
  56. if (r != EFI_SUCCESS)
  57. return NULL;
  58. memcpy(buffer, device_node->data, buffer_size);
  59. break;
  60. }
  61. break;
  62. }
  63. /*
  64. * For all node types that we do not yet support return
  65. * 'UNKNOWN(type,subtype)'.
  66. */
  67. if (!buffer) {
  68. r = efi_allocate_pool(EFI_ALLOCATE_ANY_PAGES,
  69. 2 * UNKNOWN_OUTPUT_LEN,
  70. (void **)&buffer);
  71. if (r != EFI_SUCCESS)
  72. return NULL;
  73. sprintf((char *)buffer,
  74. "UNKNOWN(%04x,%04x)",
  75. device_node->type,
  76. device_node->sub_type);
  77. for (i = UNKNOWN_OUTPUT_LEN - 1; i >= 0; --i)
  78. buffer[i] = ((uint8_t *)buffer)[i];
  79. }
  80. return buffer;
  81. }
  82. static uint16_t EFIAPI *efi_convert_device_node_to_text_ext(
  83. struct efi_device_path_protocol *device_node,
  84. bool display_only,
  85. bool allow_shortcuts)
  86. {
  87. uint16_t *buffer;
  88. EFI_ENTRY("%p, %d, %d", device_node, display_only, allow_shortcuts);
  89. buffer = efi_convert_device_node_to_text(device_node, display_only,
  90. allow_shortcuts);
  91. EFI_EXIT(EFI_SUCCESS);
  92. return buffer;
  93. }
  94. static uint16_t EFIAPI *efi_convert_device_path_to_text(
  95. struct efi_device_path_protocol *device_path,
  96. bool display_only,
  97. bool allow_shortcuts)
  98. {
  99. uint16_t *buffer;
  100. EFI_ENTRY("%p, %d, %d", device_path, display_only, allow_shortcuts);
  101. /*
  102. * Our device paths are all of depth one. So its is sufficient to
  103. * to convert the first node.
  104. */
  105. buffer = efi_convert_device_node_to_text(device_path, display_only,
  106. allow_shortcuts);
  107. EFI_EXIT(EFI_SUCCESS);
  108. return buffer;
  109. }
  110. const struct efi_device_path_to_text_protocol efi_device_path_to_text = {
  111. .convert_device_node_to_text = efi_convert_device_node_to_text_ext,
  112. .convert_device_path_to_text = efi_convert_device_path_to_text,
  113. };