]>
git.ipfire.org Git - thirdparty/u-boot.git/blob - cmd/efi.c
1 // SPDX-License-Identifier: GPL-2.0+
3 * (C) Copyright 2015 Google, Inc
4 * Written by Simon Glass <sjg@chromium.org>
13 static const char *const type_name
[] = {
30 static struct attr_info
{
34 { EFI_MEMORY_UC_SHIFT
, "uncached" },
35 { EFI_MEMORY_WC_SHIFT
, "write-coalescing" },
36 { EFI_MEMORY_WT_SHIFT
, "write-through" },
37 { EFI_MEMORY_WB_SHIFT
, "write-back" },
38 { EFI_MEMORY_UCE_SHIFT
, "uncached & exported" },
39 { EFI_MEMORY_WP_SHIFT
, "write-protect" },
40 { EFI_MEMORY_RP_SHIFT
, "read-protect" },
41 { EFI_MEMORY_XP_SHIFT
, "execute-protect" },
42 { EFI_MEMORY_RUNTIME_SHIFT
, "needs runtime mapping" }
45 /* Maximum different attribute values we can track */
46 #define ATTR_SEEN_MAX 30
48 static inline bool is_boot_services(int type
)
50 return type
== EFI_LOADER_CODE
|| type
== EFI_LOADER_DATA
||
51 type
== EFI_BOOT_SERVICES_CODE
||
52 type
== EFI_BOOT_SERVICES_DATA
;
55 static int h_cmp_entry(const void *v1
, const void *v2
)
57 const struct efi_mem_desc
*desc1
= v1
;
58 const struct efi_mem_desc
*desc2
= v2
;
59 int64_t diff
= desc1
->physical_start
- desc2
->physical_start
;
62 * Manually calculate the difference to avoid sign loss in the 64-bit
63 * to 32-bit conversion
65 return diff
< 0 ? -1 : diff
> 0 ? 1 : 0;
68 void *efi_build_mem_table(struct efi_entry_memmap
*map
, int size
, bool skip_bs
)
70 struct efi_mem_desc
*desc
, *end
, *base
, *dest
, *prev
;
74 base
= malloc(size
+ sizeof(*desc
));
76 debug("%s: Cannot allocate %#x bytes\n", __func__
, size
);
79 end
= (struct efi_mem_desc
*)((ulong
)map
+ size
);
80 count
= ((ulong
)end
- (ulong
)map
->desc
) / map
->desc_size
;
81 memcpy(base
, map
->desc
, (ulong
)end
- (ulong
)map
->desc
);
82 qsort(base
, count
, map
->desc_size
, h_cmp_entry
);
86 end
= (struct efi_mem_desc
*)((ulong
)base
+ count
* map
->desc_size
);
87 for (desc
= base
; desc
< end
; desc
= efi_get_next_mem_desc(map
, desc
)) {
89 int type
= desc
->type
;
91 if (skip_bs
&& is_boot_services(desc
->type
))
92 type
= EFI_CONVENTIONAL_MEMORY
;
94 memcpy(dest
, desc
, map
->desc_size
);
96 if (!skip_bs
|| !prev
)
98 else if (desc
->physical_start
!= addr
)
100 else if (type
!= EFI_CONVENTIONAL_MEMORY
)
102 else if (prev
->type
!= EFI_CONVENTIONAL_MEMORY
)
106 prev
->num_pages
+= desc
->num_pages
;
109 dest
= efi_get_next_mem_desc(map
, dest
);
111 addr
= desc
->physical_start
+ (desc
->num_pages
<<
116 dest
->type
= EFI_TABLE_END
;
121 static void efi_print_mem_table(struct efi_entry_memmap
*map
,
122 struct efi_mem_desc
*desc
, bool skip_bs
)
124 u64 attr_seen
[ATTR_SEEN_MAX
];
129 printf(" # %-14s %10s %10s %10s %s\n", "Type", "Physical",
130 "Virtual", "Size", "Attributes");
132 /* Keep track of all the different attributes we have seen */
135 for (upto
= 0; desc
->type
!= EFI_TABLE_END
;
136 upto
++, desc
= efi_get_next_mem_desc(map
, desc
)) {
140 if (skip_bs
&& is_boot_services(desc
->type
))
142 if (desc
->physical_start
!= addr
) {
143 printf(" %-14s %010llx %10s %010llx\n", "<gap>",
144 addr
, "", desc
->physical_start
- addr
);
146 size
= desc
->num_pages
<< EFI_PAGE_SHIFT
;
148 name
= desc
->type
< ARRAY_SIZE(type_name
) ?
149 type_name
[desc
->type
] : "<invalid>";
150 printf("%2d %x:%-12s %010llx %010llx %010llx ", upto
,
151 desc
->type
, name
, desc
->physical_start
,
152 desc
->virtual_start
, size
);
153 if (desc
->attribute
& EFI_MEMORY_RUNTIME
)
155 printf("%llx", desc
->attribute
& ~EFI_MEMORY_RUNTIME
);
158 for (i
= 0; i
< attr_seen_count
; i
++) {
159 if (attr_seen
[i
] == desc
->attribute
)
162 if (i
== attr_seen_count
&& i
< ATTR_SEEN_MAX
)
163 attr_seen
[attr_seen_count
++] = desc
->attribute
;
164 addr
= desc
->physical_start
+ size
;
167 printf("\nAttributes key:\n");
168 for (i
= 0; i
< attr_seen_count
; i
++) {
169 u64 attr
= attr_seen
[i
];
173 printf("%c%llx: ", attr
& EFI_MEMORY_RUNTIME
? 'r' : ' ',
174 attr
& ~EFI_MEMORY_RUNTIME
);
175 for (j
= 0, first
= true; j
< ARRAY_SIZE(mem_attr
); j
++) {
176 if (attr
& (1ULL << mem_attr
[j
].shift
)) {
181 printf("%s", mem_attr
[j
].name
);
187 printf("*Some areas are merged (use 'all' to see)\n");
190 static int do_efi_mem(cmd_tbl_t
*cmdtp
, int flag
, int argc
, char * const argv
[])
192 struct efi_mem_desc
*desc
;
193 struct efi_entry_memmap
*map
;
197 skip_bs
= !argc
|| *argv
[0] != 'a';
198 ret
= efi_info_get(EFIET_MEMORY_MAP
, (void **)&map
, &size
);
201 printf("No EFI table available\n");
203 case -EPROTONOSUPPORT
:
204 printf("Incorrect EFI table version\n");
207 printf("EFI table at %lx, memory map %p, size %x, version %x, descr. size %#x\n",
208 gd
->arch
.table
, map
, size
, map
->version
, map
->desc_size
);
209 if (map
->version
!= EFI_MEM_DESC_VERSION
) {
210 printf("Incorrect memory map version\n");
211 ret
= -EPROTONOSUPPORT
;
215 desc
= efi_build_mem_table(map
, size
, skip_bs
);
221 efi_print_mem_table(map
, desc
, skip_bs
);
225 printf("Error: %d\n", ret
);
227 return ret
? CMD_RET_FAILURE
: 0;
230 static cmd_tbl_t efi_commands
[] = {
231 U_BOOT_CMD_MKENT(mem
, 1, 1, do_efi_mem
, "", ""),
234 static int do_efi(cmd_tbl_t
*cmdtp
, int flag
, int argc
, char * const argv
[])
240 return CMD_RET_USAGE
;
241 efi_cmd
= find_cmd_tbl(argv
[1], efi_commands
, ARRAY_SIZE(efi_commands
));
244 if (!efi_cmd
|| argc
> efi_cmd
->maxargs
)
245 return CMD_RET_USAGE
;
247 ret
= efi_cmd
->cmd(efi_cmd
, flag
, argc
, argv
);
249 return cmd_process_error(efi_cmd
, ret
);
255 "mem [all] Dump memory information [include boot services]"