File: util.h

package info (click to toggle)
stubble 3-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 836 kB
  • sloc: ansic: 6,119; python: 599; makefile: 40
file content (158 lines) | stat: -rw-r--r-- 6,182 bytes parent folder | download | duplicates (2)
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
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once

#include "efi.h"
#include "memory-util-fundamental.h"

#include "proto/file-io.h"

/* This is provided by the linker. */
extern uint8_t __executable_start[];

DISABLE_WARNING_REDUNDANT_DECLS;
void free(void *p);
REENABLE_WARNING;

static inline void freep(void *p) {
        free(*(void **) p);
}

#define _cleanup_free_ _cleanup_(freep)

_malloc_ _alloc_(1) _returns_nonnull_ _warn_unused_result_
void *xmalloc(size_t size);

_malloc_ _alloc_(1) _returns_nonnull_ _warn_unused_result_
static inline void *xcalloc(size_t size) {
        void *t = xmalloc(size);
        memzero(t, size);
        return t;
}

_malloc_ _alloc_(1, 2) _returns_nonnull_ _warn_unused_result_
static inline void *xcalloc_multiply(size_t n, size_t size) {
        assert_se(MUL_ASSIGN_SAFE(&size, n));
        return xcalloc(size);
}

_malloc_ _alloc_(1, 2) _returns_nonnull_ _warn_unused_result_
static inline void *xmalloc_multiply(size_t n, size_t size) {
        assert_se(MUL_ASSIGN_SAFE(&size, n));
        return xmalloc(size);
}

/* Use malloc attribute as this never returns p like userspace realloc. */
_malloc_ _alloc_(3) _returns_nonnull_ _warn_unused_result_
static inline void *xrealloc(void *p, size_t old_size, size_t new_size) {
        void *t = xmalloc(new_size);
        new_size = MIN(old_size, new_size);
        if (new_size > 0)
                memcpy(t, p, new_size);
        free(p);
        return t;
}

_malloc_ _alloc_(2) _returns_nonnull_ _warn_unused_result_
static inline void* xmemdup(const void *p, size_t l) {
        return memcpy(xmalloc(l), p, l);
}

#define xnew(type, n) ((type *) xmalloc_multiply((n), sizeof(type)))
#define xnew0(type, n) ((type *) xcalloc_multiply((n), sizeof(type)))

typedef struct {
        EFI_PHYSICAL_ADDRESS addr;
        size_t n_pages;
} Pages;

static inline void cleanup_pages(Pages *p) {
        if (p->n_pages == 0)
                return;
#ifdef EFI_DEBUG
        assert_se(BS->FreePages(p->addr, p->n_pages) == EFI_SUCCESS);
#else
        (void) BS->FreePages(p->addr, p->n_pages);
#endif
}

#define _cleanup_pages_ _cleanup_(cleanup_pages)

static inline Pages xmalloc_pages(
                EFI_ALLOCATE_TYPE type, EFI_MEMORY_TYPE memory_type, size_t n_pages, EFI_PHYSICAL_ADDRESS addr) {
        assert_se(BS->AllocatePages(type, memory_type, n_pages, &addr) == EFI_SUCCESS);
        return (Pages) {
                .addr = addr,
                .n_pages = n_pages,
        };
}

char16_t *mangle_stub_cmdline(char16_t *cmdline);

/* Note that GUID is evaluated multiple times! */
#define GUID_FORMAT_STR "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X"
#define GUID_FORMAT_VAL(g) (g).Data1, (g).Data2, (g).Data3, (g).Data4[0], (g).Data4[1], \
        (g).Data4[2], (g).Data4[3], (g).Data4[4], (g).Data4[5], (g).Data4[6], (g).Data4[7]

/* Conversion between EFI_PHYSICAL_ADDRESS and pointers is not obvious. The former is always 64-bit, even on
 * 32-bit archs. And gcc complains if we cast a pointer to an integer of a different size. Hence let's do the
 * conversion indirectly: first into uintptr_t and then extended to EFI_PHYSICAL_ADDRESS. */
static inline EFI_PHYSICAL_ADDRESS POINTER_TO_PHYSICAL_ADDRESS(const void *p) {
        return (EFI_PHYSICAL_ADDRESS) (uintptr_t) p;
}

static inline void *PHYSICAL_ADDRESS_TO_POINTER(EFI_PHYSICAL_ADDRESS addr) {
        /* On 32-bit systems the address might not be convertible (as pointers are 32-bit but
         * EFI_PHYSICAL_ADDRESS 64-bit) */
        assert(addr <= UINTPTR_MAX);
        return (void *) (uintptr_t) addr;
}

/* If EFI_DEBUG, print our name and version and also report the address of the image base so a debugger can
 * be attached. See debug-sd-boot.sh for how this can be done. */
void notify_debugger(const char *identity, bool wait);

/* On x86 the compiler assumes a different incoming stack alignment than what we get.
 * This will cause long long variables to be misaligned when building with
 * '-mlong-double' (for correct struct layouts). Normally, the compiler realigns the
 * stack itself on entry, but we have to do this ourselves here as the compiler does
 * not know that this is our entry point. */
#ifdef __i386__
#  define _realign_stack_ __attribute__((force_align_arg_pointer))
#else
#  define _realign_stack_
#endif

#define DEFINE_EFI_MAIN_FUNCTION(func, identity, wait_for_debugger)                    \
        EFI_SYSTEM_TABLE *ST;                                                          \
        EFI_BOOT_SERVICES *BS;                                                         \
        EFI_RUNTIME_SERVICES *RT;                                                      \
        _realign_stack_                                                                \
        EFIAPI EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *system_table);  \
        EFIAPI EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *system_table) { \
                ST = system_table;                                                     \
                BS = system_table->BootServices;                                       \
                RT = system_table->RuntimeServices;                                    \
                __stack_chk_guard_init();                                              \
                notify_debugger((identity), (wait_for_debugger));                      \
                EFI_STATUS err = func(image);                                          \
                log_wait();                                                            \
                return err;                                                            \
        }

static inline bool efi_guid_equal(const EFI_GUID *a, const EFI_GUID *b) {
        return memcmp(a, b, sizeof(EFI_GUID)) == 0;
}

void *find_configuration_table(const EFI_GUID *guid);

#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#  define be16toh(x) __builtin_bswap16(x)
#  define be32toh(x) __builtin_bswap32(x)
#  define le16toh(x) (x)
#  define le32toh(x) (x)
#else
#  error "Unexpected byte order in EFI mode?"
#endif

#define bswap_16(x) __builtin_bswap16(x)
#define bswap_32(x) __builtin_bswap32(x)