2 * This file is part of the coreboot project.
4 * Copyright (C) 2003-2004 Eric Biederman
5 * Copyright (C) 2005-2010 coresystems GmbH
6 * Copyright (C) 2014 Google Inc.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
18 #include <console/console.h>
21 #include <device/resource.h>
24 static struct memranges bootmem
;
26 void bootmem_init(void)
28 const unsigned long cacheable
= IORESOURCE_CACHEABLE
;
29 const unsigned long reserved
= IORESOURCE_RESERVE
;
30 struct memranges
*bm
= &bootmem
;
33 * Fill the memory map out. The order of operations is important in
34 * that each overlapping range will take over the next. Therefore,
35 * add cacheable resources as RAM then add the reserved resources.
37 memranges_init(bm
, cacheable
, cacheable
, LB_MEM_RAM
);
38 memranges_add_resources(bm
, reserved
, reserved
, LB_MEM_RESERVED
);
40 /* Add memory used by CBMEM. */
43 bootmem_arch_add_ranges();
46 void bootmem_add_range(uint64_t start
, uint64_t size
, uint32_t type
)
48 memranges_insert(&bootmem
, start
, size
, type
);
51 void bootmem_write_memory_table(struct lb_memory
*mem
)
53 const struct range_entry
*r
;
54 struct lb_memory_range
*lb_r
;
58 bootmem_dump_ranges();
60 memranges_each_entry(r
, &bootmem
) {
61 lb_r
->start
= pack_lb64(range_entry_base(r
));
62 lb_r
->size
= pack_lb64(range_entry_size(r
));
63 lb_r
->type
= range_entry_tag(r
);
66 mem
->size
+= sizeof(struct lb_memory_range
);
70 struct range_strings
{
75 static const struct range_strings type_strings
[] = {
76 { LB_MEM_RAM
, "RAM" },
77 { LB_MEM_RESERVED
, "RESERVED" },
78 { LB_MEM_ACPI
, "ACPI" },
79 { LB_MEM_NVS
, "NVS" },
80 { LB_MEM_UNUSABLE
, "UNUSABLE" },
81 { LB_MEM_VENDOR_RSVD
, "VENDOR RESERVED" },
82 { LB_MEM_TABLE
, "CONFIGURATION TABLES" },
85 static const char *bootmem_range_string(unsigned long tag
)
89 for (i
= 0; i
< ARRAY_SIZE(type_strings
); i
++) {
90 if (type_strings
[i
].tag
== tag
)
91 return type_strings
[i
].str
;
97 void bootmem_dump_ranges(void)
100 const struct range_entry
*r
;
103 memranges_each_entry(r
, &bootmem
) {
104 printk(BIOS_DEBUG
, "%2d. %016llx-%016llx: %s\n",
105 i
, range_entry_base(r
), range_entry_end(r
) - 1,
106 bootmem_range_string(range_entry_tag(r
)));
111 int bootmem_region_targets_usable_ram(uint64_t start
, uint64_t size
)
113 const struct range_entry
*r
;
114 uint64_t end
= start
+ size
;
116 memranges_each_entry(r
, &bootmem
) {
117 /* All further bootmem entries are beyond this range. */
118 if (end
<= range_entry_base(r
))
121 if (start
>= range_entry_base(r
) && end
<= range_entry_end(r
)) {
122 if (range_entry_tag(r
) == LB_MEM_RAM
)
129 void *bootmem_allocate_buffer(size_t size
)
131 const struct range_entry
*r
;
132 const struct range_entry
*region
;
133 /* All allocated buffers fall below the 32-bit boundary. */
134 const resource_t max_addr
= 1ULL << 32;
138 /* 4KiB alignment. */
139 size
= ALIGN(size
, 4096);
141 memranges_each_entry(r
, &bootmem
) {
142 if (range_entry_size(r
) < size
)
145 if (range_entry_tag(r
) != LB_MEM_RAM
)
148 if (range_entry_base(r
) >= max_addr
)
151 end
= range_entry_end(r
);
155 if ((end
- range_entry_base(r
)) < size
)
164 /* region now points to the highest usable region for the given size. */
165 begin
= range_entry_base(region
);
166 end
= range_entry_end(region
);
171 /* Mark buffer as unusuable for future buffer use. */
172 bootmem_add_range(begin
, size
, LB_MEM_UNUSABLE
);
174 return (void *)(uintptr_t)begin
;