efi_load_options.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * EFI boot manager
  4. *
  5. * Copyright (c) 2018 AKASHI Takahiro, et.al.
  6. */
  7. #define LOG_CATEGORY LOGC_EFI
  8. #include <common.h>
  9. #include <charset.h>
  10. #include <log.h>
  11. #include <malloc.h>
  12. #include <efi_loader.h>
  13. #include <asm/unaligned.h>
  14. /**
  15. * efi_set_load_options() - set the load options of a loaded image
  16. *
  17. * @handle: the image handle
  18. * @load_options_size: size of load options
  19. * @load_options: pointer to load options
  20. * Return: status code
  21. */
  22. efi_status_t efi_set_load_options(efi_handle_t handle,
  23. efi_uintn_t load_options_size,
  24. void *load_options)
  25. {
  26. struct efi_loaded_image *loaded_image_info;
  27. struct efi_handler *handler;
  28. efi_status_t ret;
  29. ret = efi_search_protocol(handle, &efi_guid_loaded_image, &handler);
  30. if (ret != EFI_SUCCESS)
  31. return EFI_INVALID_PARAMETER;
  32. loaded_image_info = handler->protocol_interface;
  33. loaded_image_info->load_options = load_options;
  34. loaded_image_info->load_options_size = load_options_size;
  35. return EFI_SUCCESS;
  36. }
  37. /**
  38. * efi_deserialize_load_option() - parse serialized data
  39. *
  40. * Parse serialized data describing a load option and transform it to the
  41. * efi_load_option structure.
  42. *
  43. * @lo: pointer to target
  44. * @data: serialized data
  45. * @size: size of the load option, on return size of the optional data
  46. * Return: status code
  47. */
  48. efi_status_t efi_deserialize_load_option(struct efi_load_option *lo, u8 *data,
  49. efi_uintn_t *size)
  50. {
  51. efi_uintn_t len;
  52. len = sizeof(u32);
  53. if (*size < len + 2 * sizeof(u16))
  54. return EFI_INVALID_PARAMETER;
  55. lo->attributes = get_unaligned_le32(data);
  56. data += len;
  57. *size -= len;
  58. len = sizeof(u16);
  59. lo->file_path_length = get_unaligned_le16(data);
  60. data += len;
  61. *size -= len;
  62. lo->label = (u16 *)data;
  63. len = u16_strnlen(lo->label, *size / sizeof(u16) - 1);
  64. if (lo->label[len])
  65. return EFI_INVALID_PARAMETER;
  66. len = (len + 1) * sizeof(u16);
  67. if (*size < len)
  68. return EFI_INVALID_PARAMETER;
  69. data += len;
  70. *size -= len;
  71. len = lo->file_path_length;
  72. if (*size < len)
  73. return EFI_INVALID_PARAMETER;
  74. lo->file_path = (struct efi_device_path *)data;
  75. if (efi_dp_check_length(lo->file_path, len) < 0)
  76. return EFI_INVALID_PARAMETER;
  77. data += len;
  78. *size -= len;
  79. lo->optional_data = data;
  80. return EFI_SUCCESS;
  81. }
  82. /**
  83. * efi_serialize_load_option() - serialize load option
  84. *
  85. * Serialize efi_load_option structure into byte stream for BootXXXX.
  86. *
  87. * @data: buffer for serialized data
  88. * @lo: load option
  89. * Return: size of allocated buffer
  90. */
  91. unsigned long efi_serialize_load_option(struct efi_load_option *lo, u8 **data)
  92. {
  93. unsigned long label_len;
  94. unsigned long size;
  95. u8 *p;
  96. label_len = u16_strsize(lo->label);
  97. /* total size */
  98. size = sizeof(lo->attributes);
  99. size += sizeof(lo->file_path_length);
  100. size += label_len;
  101. size += lo->file_path_length;
  102. if (lo->optional_data)
  103. size += (utf8_utf16_strlen((const char *)lo->optional_data)
  104. + 1) * sizeof(u16);
  105. p = malloc(size);
  106. if (!p)
  107. return 0;
  108. /* copy data */
  109. *data = p;
  110. memcpy(p, &lo->attributes, sizeof(lo->attributes));
  111. p += sizeof(lo->attributes);
  112. memcpy(p, &lo->file_path_length, sizeof(lo->file_path_length));
  113. p += sizeof(lo->file_path_length);
  114. memcpy(p, lo->label, label_len);
  115. p += label_len;
  116. memcpy(p, lo->file_path, lo->file_path_length);
  117. p += lo->file_path_length;
  118. if (lo->optional_data) {
  119. utf8_utf16_strcpy((u16 **)&p, (const char *)lo->optional_data);
  120. p += sizeof(u16); /* size of trailing \0 */
  121. }
  122. return size;
  123. }