Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 | /* SPDX-License-Identifier: GPL-2.0+ */ /* * Logging (to memory) of calls from an EFI app * * Copyright 2024 Google LLC * Written by Simon Glass <sjg@chromium.org> */ #ifndef __EFI_LOG_H #define __EFI_LOG_H #include <linux/types.h> #include <efi.h> /** * enum efil_tag - Types of logging records which can be created */ enum efil_tag { EFILT_ALLOCATE_PAGES, EFILT_FREE_PAGES, EFILT_ALLOCATE_POOL, EFILT_FREE_POOL, EFILT_TESTING, EFILT_COUNT, }; /** * struct efil_rec_hdr - Header for each logging record * * @tag: Tag which indicates the type of the record * @size: Size of the record in bytes * @ended: true if record has been completed (i.e. the function returned), false * if it is still pending * @e_ret: Records the return function from the logged function */ struct efil_rec_hdr { enum efil_tag tag; int size; bool ended; efi_status_t e_ret; }; /** * struct efil_hdr - Holds the header for the log * * @upto: Offset at which to store the next log record * @size: Total size of the log in bytes */ struct efil_hdr { int upto; int size; }; enum efil_test_t { EFI_LOG_TEST0, EFI_LOG_TEST1, EFI_LOG_TEST_COUNT, }; /** * struct efil_testing - used for testing the log */ struct efil_testing { enum efil_test_t enum_val; efi_uintn_t int_val; u64 *memory; void **buffer; u64 e_memory; void *e_buffer; }; /** * struct efil_allocate_pages - holds info from efi_allocate_pages() call * * @e_memory: Contains the value of *@memory on return from the EFI function */ struct efil_allocate_pages { enum efi_allocate_type type; enum efi_memory_type memory_type; efi_uintn_t pages; u64 *memory; u64 e_memory; }; /** struct efil_free_pages - holds info from efi_free_pages() call */ struct efil_free_pages { u64 memory; efi_uintn_t pages; }; /** struct efil_allocate_pool - holds info from efi_allocate_pool() call * * @e_buffer: Contains the value of *@buffer on return from the EFI function */ struct efil_allocate_pool { enum efi_memory_type pool_type; efi_uintn_t size; void **buffer; void *e_buffer; }; /** struct efil_free_pool - holds log-info from efi_free_pool() call */ struct efil_free_pool { void *buffer; }; /* * The functions below are in pairs, with a 'start' and 'end' call for each EFI * function. The 'start' function (efi_logs_...) is called when the function is * started. It records all the arguments. The 'end' function (efi_loge_...) is * called when the function is ready to return. It records any output arguments * as well as the return value. * * The start function returns the offset of the log record. This must be passed * to the end function, so it can add the status code and any other useful * information. It is not possible for the end functions to remember the offset * from the associated start function, since EFI functions may be called in a * nested way and there is no obvious way to determine the log record to which * the end function refers. * * If the start function returns an error code (i.e. an offset < 0) then it is * safe to pass that to the end function. It will simply ignore the operation. * Common errors are -ENOENT if there is no log and -ENOSPC if the log is full */ #if CONFIG_IS_ENABLED(EFI_LOG) /** * efi_logs_testing() - Record a test call to an efi function * * @enum_val: enum value * @int_val: integer value * @buffer: place to write pointer address * @memory: place to write memory address * Return: log-offset of this new record, or -ve error code */ int efi_logs_testing(enum efil_test_t enum_val, efi_uintn_t int_value, void *buffer, u64 *memory); /** * efi_loge_testing() - Record a return from a test call * * This stores the value of the pointers also * * ofs: Offset of the record to end * efi_ret: status code to record */ int efi_loge_testing(int ofs, efi_status_t efi_ret); /** * efi_logs_allocate_pages() - Record a call to efi_allocate_pages() * * @type: type of allocation to be performed * @memory_type: usage type of the allocated memory * @pages: number of pages to be allocated * @memory: place to write address of allocated memory * Return: log-offset of this new record, or -ve error code */ int efi_logs_allocate_pages(enum efi_allocate_type type, enum efi_memory_type memory_type, efi_uintn_t pages, u64 *memory); /** * efi_loge_allocate_pages() - Record a return from efi_allocate_pages() * * This stores the value of the memory pointer also * * ofs: Offset of the record to end * efi_ret: status code to record */ int efi_loge_allocate_pages(int ofs, efi_status_t efi_ret); /** * efi_logs_free_pages() - Record a call to efi_free_pages() * * @memory: start of the memory area to be freed * @pages: number of pages to be freed * Return: log-offset of this new record, or -ve error code */ int efi_logs_free_pages(u64 memory, efi_uintn_t pages); /** * efi_loge_free_pages() - Record a return from efi_free_pages() * * ofs: Offset of the record to end * efi_ret: status code to record */ int efi_loge_free_pages(int ofs, efi_status_t efi_ret); /** * efi_logs_allocate_pool() - Record a call to efi_allocate_pool() * * @pool_type: type of the pool from which memory is to be allocated * @size: number of bytes to be allocated * @buffer: place to hold pointer to allocated memory * Return: log-offset of this new record, or -ve error code */ int efi_logs_allocate_pool(enum efi_memory_type pool_type, efi_uintn_t size, void **buffer); /** * efi_loge_allocate_pool() - Record a return from efi_allocate_pool() * * This stores the value of the buffer pointer also * * ofs: Offset of the record to end * efi_ret: status code to record */ int efi_loge_allocate_pool(int ofs, efi_status_t efi_ret); /** * efi_logs_free_pool() - Record a call to efi_free_pool() * * @buffer: start of memory to be freed * Return: log-offset of this new record, or -ve error code */ int efi_logs_free_pool(void *buffer); /** * efi_loge_free_pool() - Record a return from efi_free_pool() * * ofs: Offset of the record to end * efi_ret: status code to record */ int efi_loge_free_pool(int ofs, efi_status_t efi_ret); #else /* !EFI_LOG */ static inline int efi_logs_allocate_pages(enum efi_allocate_type type, enum efi_memory_type memory_type, efi_uintn_t pages, u64 *memory) { return -ENOSYS; } static inline int efi_loge_allocate_pages(int ofs, efi_status_t efi_ret) { return -ENOSYS; } static inline int efi_logs_free_pages(u64 memory, efi_uintn_t pages) { return -ENOSYS; } static inline int efi_loge_free_pages(int ofs, efi_status_t efi_ret) { return -ENOSYS; } static inline int efi_logs_allocate_pool(enum efi_memory_type pool_type, efi_uintn_t size, void **buffer) { return -ENOSYS; } static inline int efi_loge_allocate_pool(int ofs, efi_status_t efi_ret) { return -ENOSYS; } static inline int efi_logs_free_pool(void *buffer) { return -ENOSYS; } static inline int efi_loge_free_pool(int ofs, efi_status_t efi_ret) { return -ENOSYS; } static inline int efi_logs_testing(enum efil_test_t enum_val, efi_uintn_t int_value, void *buffer, u64 *memory) { return -ENOSYS; } static inline int efi_loge_testing(int ofs, efi_status_t efi_ret) { return -ENOSYS; } #endif /* EFI_LOG */ /* below are some general functions */ /** * efi_log_show() - Show the EFI log * * Displays the log of EFI boot-services calls which are so-far enabled for * logging * * Return: 0 on success, or -ve error code */ int efi_log_show(void); /** * efi_log_reset() - Reset the log, erasing all records * * Return 0 if OK, -ENOENT if the log could not be found */ int efi_log_reset(void); /** * efi_log_init() - Create a log in the bloblist, then reset it * * Return 0 if OK, -ENOMEM if the bloblist is not large enough */ int efi_log_init(void); #endif /* __EFI_LOG_H */ |