Page MenuHomeFreeBSD

D22569.id64937.diff
No OneTemporary

D22569.id64937.diff

Index: stand/efi/loader/copy.c
===================================================================
--- stand/efi/loader/copy.c
+++ stand/efi/loader/copy.c
@@ -185,7 +185,7 @@
#endif
#endif
-EFI_PHYSICAL_ADDRESS staging, staging_end;
+EFI_PHYSICAL_ADDRESS staging, staging_end, staging_base;
int stage_offset_set = 0;
ssize_t stage_offset;
@@ -224,6 +224,7 @@
EFI_ERROR_CODE(status));
return (status);
}
+ staging_base = staging;
staging_end = staging + nr_pages * EFI_PAGE_SIZE;
#if defined(__aarch64__) || defined(__arm__)
@@ -240,6 +241,66 @@
return (0);
}
+static bool
+efi_check_space(vm_offset_t end)
+{
+ EFI_PHYSICAL_ADDRESS addr;
+ EFI_STATUS status;
+ unsigned long nr_pages;
+
+ /* There is already enough space */
+ if (end <= staging_end)
+ return (true);
+
+ end = roundup2(end, EFI_PAGE_SIZE);
+ nr_pages = EFI_SIZE_TO_PAGES(end - staging_end);
+
+#if defined(__i386__) || defined(__amd64__)
+ /* X86 needs all memory to be allocated under the 1G boundary */
+ if (end > 1024*1024*1024)
+ goto before_staging;
+#endif
+
+ /* Try to allocate more space after the previous allocation */
+ addr = staging_end;
+ status = BS->AllocatePages(AllocateAddress, EfiLoaderData, nr_pages,
+ &addr);
+ if (!EFI_ERROR(status)) {
+ staging_end = staging_end + nr_pages * EFI_PAGE_SIZE;
+ return (true);
+ }
+
+before_staging:
+ /* Try allocating space before the previous allocation */
+ if (staging < nr_pages * EFI_PAGE_SIZE) {
+ printf("Not enough space before allocation\n");
+ return (false);
+ }
+ addr = staging - nr_pages * EFI_PAGE_SIZE;
+#if defined(__aarch64__) || defined(__arm__)
+ /* See efi_copy_init for why this is needed */
+ addr = rounddown2(addr, 2 * 1024 * 1024);
+#endif
+ nr_pages = EFI_SIZE_TO_PAGES(staging_base - addr);
+ status = BS->AllocatePages(AllocateAddress, EfiLoaderData, nr_pages,
+ &addr);
+ if (!EFI_ERROR(status)) {
+ /*
+ * Move the old allocation and update the state so
+ * translation still works.
+ */
+ staging_base = addr;
+ memmove((void *)staging_base, (void *)staging,
+ staging_end - staging);
+ stage_offset -= (staging - staging_base);
+ staging = staging_base;
+ return (true);
+ }
+
+ printf("efi_check_space: Unable to expand staging area\n");
+ return (false);
+}
+
void *
efi_translate(vm_offset_t ptr)
{
@@ -257,7 +318,7 @@
}
/* XXX: Callers do not check for failure. */
- if (dest + stage_offset + len > staging_end) {
+ if (!efi_check_space(dest + stage_offset + len)) {
errno = ENOMEM;
return (-1);
}
@@ -283,7 +344,7 @@
efi_readin(const int fd, vm_offset_t dest, const size_t len)
{
- if (dest + stage_offset + len > staging_end) {
+ if (!efi_check_space(dest + stage_offset + len)) {
errno = ENOMEM;
return (-1);
}

File Metadata

Mime Type
text/plain
Expires
Fri, Jan 24, 8:55 PM (20 h, 19 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16103093
Default Alt Text
D22569.id64937.diff (2 KB)

Event Timeline