vmbase: Define .image_footer linker section

Replace the runtime memory reservation for the footer with a linker
defined placeholder. Keep this uniform across the clients instead of
making it specific for the pvmfw.

Note: no functional change intended.

Bug: 377276983
Test: m {pvmfw,rialto,vmbase_example_{bios,kernel}}_bin
Change-Id: I46ca02f68af6e0c135a1b6bf9f0701388ca9a445
diff --git a/guest/pvmfw/src/entry.rs b/guest/pvmfw/src/entry.rs
index 39e51c5..48585f3 100644
--- a/guest/pvmfw/src/entry.rs
+++ b/guest/pvmfw/src/entry.rs
@@ -129,7 +129,7 @@
         page_table,
         crosvm::MEM_START..layout::MAX_VIRT_ADDR,
         crosvm::MMIO_RANGE,
-        Some(memory::appended_payload_range()),
+        Some(layout::image_footer_range()),
     ));
 
     let slices = memory::MemorySlices::new(
@@ -326,7 +326,7 @@
 /// This must only be called once, since we are returning a mutable reference.
 /// The appended data region must be mapped.
 unsafe fn get_appended_data_slice() -> &'static mut [u8] {
-    let range = memory::appended_payload_range();
+    let range = layout::image_footer_range();
     // SAFETY: This region is mapped and the linker script prevents it from overlapping with other
     // objects.
     unsafe { slice::from_raw_parts_mut(range.start.0 as *mut u8, range.end - range.start) }
diff --git a/guest/pvmfw/src/memory.rs b/guest/pvmfw/src/memory.rs
index 67a95f4..7d49bca 100644
--- a/guest/pvmfw/src/memory.rs
+++ b/guest/pvmfw/src/memory.rs
@@ -30,18 +30,9 @@
 use log::warn;
 use vmbase::{
     layout::{self, crosvm},
-    memory::{PageTable, MEMORY, SIZE_2MB, SIZE_4KB},
-    util::align_up,
+    memory::{PageTable, MEMORY},
 };
 
-/// Returns memory range reserved for the appended payload.
-pub fn appended_payload_range() -> Range<VirtualAddress> {
-    let start = align_up(layout::binary_end().0, SIZE_4KB).unwrap();
-    // pvmfw is contained in a 2MiB region so the payload can't be larger than the 2MiB alignment.
-    let end = align_up(start, SIZE_2MB).unwrap();
-    VirtualAddress(start)..VirtualAddress(end)
-}
-
 /// Region allocated for the stack.
 pub fn stack_range() -> Range<VirtualAddress> {
     const STACK_PAGES: usize = 12;
@@ -59,7 +50,7 @@
     page_table.map_data(&stack_range().into())?;
     page_table.map_code(&layout::text_range().into())?;
     page_table.map_rodata(&layout::rodata_range().into())?;
-    page_table.map_data_dbm(&appended_payload_range().into())?;
+    page_table.map_data_dbm(&layout::image_footer_range().into())?;
     if let Err(e) = page_table.map_device(&layout::console_uart_page().into()) {
         error!("Failed to remap the UART as a dynamic page table entry: {e}");
         return Err(e);
diff --git a/libs/libvmbase/sections.ld b/libs/libvmbase/sections.ld
index 61af60f..222edae 100644
--- a/libs/libvmbase/sections.ld
+++ b/libs/libvmbase/sections.ld
@@ -76,6 +76,13 @@
 	/* Everything beyond this point will not be included in the binary. */
 	bin_end = data_lma + SIZEOF(.data);
 
+	/* Data may be appended at load time to our binary. */
+	.image_footer (NOLOAD) : ALIGN(4096) {
+		image_footer_begin = .;
+		. = ALIGN(LENGTH(image));
+		image_footer_end = .;
+	} >image
+
 	/* The entry point code assumes that .bss is 16-byte aligned. */
 	.bss : ALIGN(16)  {
 		bss_begin = .;
diff --git a/libs/libvmbase/src/layout.rs b/libs/libvmbase/src/layout.rs
index 2f710ef..a8f7827 100644
--- a/libs/libvmbase/src/layout.rs
+++ b/libs/libvmbase/src/layout.rs
@@ -70,6 +70,11 @@
     linker_region!(rodata_begin, rodata_end)
 }
 
+/// Region which may contain a footer appended to the binary at load time.
+pub fn image_footer_range() -> Range<VirtualAddress> {
+    linker_region!(image_footer_begin, image_footer_end)
+}
+
 /// Initialised writable data.
 pub fn data_range() -> Range<VirtualAddress> {
     linker_region!(data_begin, data_end)
diff --git a/libs/libvmbase/src/linker.rs b/libs/libvmbase/src/linker.rs
index 40afce5..8654cf9 100644
--- a/libs/libvmbase/src/linker.rs
+++ b/libs/libvmbase/src/linker.rs
@@ -35,6 +35,10 @@
     pub static dtb_end: u8;
     /// First byte of the region available for the exception handler stack.
     pub static eh_stack_limit: u8;
+    /// First byte of the `.image_footer` section.
+    pub static image_footer_begin: u8;
+    /// First byte beyond the `.image_footer` section.
+    pub static image_footer_end: u8;
     /// First byte past the region available for the exception handler stack.
     pub static init_eh_stack_pointer: u8;
     /// First byte past the region available for the stack.