iPXE
memmap.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2025 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 
26 #include <assert.h>
27 #include <ipxe/io.h>
28 #include <ipxe/memmap.h>
29 
30 /** @file
31  *
32  * System memory map
33  *
34  */
35 
36 /**
37  * Update memory region descriptor
38  *
39  * @v region Memory region of interest to be updated
40  * @v start Start address of known region
41  * @v size Size of known region
42  * @v flags Flags for known region
43  * @v name Name of known region (for debugging)
44  *
45  * Update a memory region descriptor based on a known existent region.
46  */
47 void memmap_update ( struct memmap_region *region, uint64_t start,
48  uint64_t size, unsigned int flags, const char *name ) {
49  uint64_t max;
50 
51  /* Sanity check */
52  assert ( region->max >= region->min );
53 
54  /* Ignore empty regions */
55  if ( ! size )
56  return;
57 
58  /* Calculate max addresses (and truncate if necessary) */
59  max = ( start + size - 1 );
60  if ( max < start ) {
61  max = ~( ( uint64_t ) 0 );
62  DBGC ( region, "MEMMAP [%#08llx,%#08llx] %s truncated "
63  "(invalid size %#08llx)\n",
64  ( ( unsigned long long ) start ),
65  ( ( unsigned long long ) max ), name,
66  ( ( unsigned long long ) size ) );
67  }
68 
69  /* Ignore regions entirely below the region of interest */
70  if ( max < region->min )
71  return;
72 
73  /* Ignore regions entirely above the region of interest */
74  if ( start > region->max )
75  return;
76 
77  /* Update region of interest as applicable */
78  if ( start <= region->min ) {
79 
80  /* Record this region as covering the region of interest */
81  region->flags |= flags;
82  if ( name )
83  region->name = name;
84 
85  /* Update max address if no closer boundary exists */
86  if ( max < region->max )
87  region->max = max;
88 
89  } else if ( start < region->max ) {
90 
91  /* Update max address if no closer boundary exists */
92  region->max = ( start - 1 );
93  }
94 
95  /* Sanity check */
96  assert ( region->max >= region->min );
97 }
98 
99 /**
100  * Update memory region descriptor based on all in-use memory regions
101  *
102  * @v region Memory region of interest to be updated
103  */
104 void memmap_update_used ( struct memmap_region *region ) {
105  struct used_region *used;
106 
107  /* Update descriptor to hide all in-use regions */
109  memmap_update ( region, used->start, used->size,
110  MEMMAP_FL_USED, used->name );
111  }
112 }
113 
114 /**
115  * Find largest usable memory region
116  *
117  * @v start Start address to fill in
118  * @ret len Length of region
119  */
121  struct memmap_region region;
122  size_t largest;
123  size_t size;
124 
125  /* Find largest usable region */
126  DBGC ( &region, "MEMMAP finding largest usable region\n" );
127  *start = 0;
128  largest = 0;
129  for_each_memmap ( &region, 1 ) {
130  DBGC_MEMMAP ( &region, &region );
131  if ( ! memmap_is_usable ( &region ) )
132  continue;
133  size = memmap_size ( &region );
134  if ( size > largest ) {
135  DBGC ( &region, "...new largest region found\n" );
136  largest = size;
137  *start = region.min;
138  }
139  }
140  return largest;
141 }
142 
static int memmap_is_usable(const struct memmap_region *region)
Check if memory region is usable.
Definition: memmap.h:86
size_t size
Length of region.
Definition: memmap.h:111
size_t memmap_largest(physaddr_t *start)
Find largest usable memory region.
Definition: memmap.c:120
iPXE I/O API
const char * name
Definition: ath9k_hw.c:1984
void memmap_update(struct memmap_region *region, uint64_t start, uint64_t size, unsigned int flags, const char *name)
Update memory region descriptor.
Definition: memmap.c:47
#define max(x, y)
Definition: ath.h:40
uint64_t max
Maximum address in region.
Definition: memmap.h:52
#define USED_REGIONS
In-use memory region table.
Definition: memmap.h:115
uint16_t size
Buffer size.
Definition: dwmac.h:14
#define DBGC(...)
Definition: compiler.h:505
#define min(x, y)
Definition: ath.h:35
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
unsigned long long uint64_t
Definition: stdint.h:13
#define DBGC_MEMMAP(...)
Definition: memmap.h:206
#define MEMMAP_FL_USED
Is in use by iPXE.
Definition: memmap.h:61
uint32_t start
Starting offset.
Definition: netvsc.h:12
physaddr_t start
Start address.
Definition: memmap.h:109
PROVIDE_MEMMAP_INLINE(null, memmap_describe)
void memmap_describe(uint64_t min, int hide, struct memmap_region *region)
Describe memory region from system memory map.
Definition: null_memmap.h:28
Assertions.
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
#define for_each_memmap(region, hide)
Iterate over memory regions.
Definition: memmap.h:183
uint8_t flags
Flags.
Definition: ena.h:18
An in-use memory region.
Definition: memmap.h:105
unsigned int flags
Region flags.
Definition: memmap.h:54
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition: tables.h:385
const char * name
Region name (for debug messages)
Definition: memmap.h:56
unsigned long physaddr_t
Definition: stdint.h:20
static uint64_t memmap_size(const struct memmap_region *region)
Get remaining size of memory region (from the described address upwards)
Definition: memmap.h:98
static memmap_sync(void)
Synchronise in-use regions with the externally visible system memory map.
Definition: fdtmem.h:25
const char * name
Region name.
Definition: memmap.h:107
uint64_t min
Minimum address in region.
Definition: memmap.h:50
A memory region descriptor.
Definition: memmap.h:48
System memory map.
void memmap_update_used(struct memmap_region *region)
Update memory region descriptor based on all in-use memory regions.
Definition: memmap.c:104