3 * This file is subject to the terms and conditions of the GNU General Public
4 * License. See the file "COPYING" in the main directory of this archive
7 * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved.
13 * FPROM EFI memory descriptor build routines
15 * - Routines to build the EFI memory descriptor map
16 * - Should also be usable by the SGI prom to convert
17 * klconfig to efi_memmap
20 #include <linux/config.h>
21 #include <linux/efi.h>
25 * args points to a layout in memory like this
31 * 16 bit 16 bit 32 bit
32 * nasid0 cpuconf membankdesc0
33 * nasid1 cpuconf membankdesc1
41 sn_memmap_t *sn_memmap ;
42 sn_config_t *sn_config ;
45 * There is a hole in the node 0 address space. Dont put it
48 #define NODE0_HOLE_SIZE (20*MB)
49 #define NODE0_HOLE_END (4UL*GB)
51 #define MB (1024*1024)
53 #define KERNEL_SIZE (4*MB)
54 #define PROMRESERVED_SIZE (1*MB)
57 #define PHYS_ADDRESS(_n, _x) (((long)_n<<38) | (long)_x | 0x3000000000UL)
58 #define MD_BANK_SHFT 34
62 * For SN, this may not take an arg and gets the numnodes from
63 * the prom variable or by traversing klcfg or promcfg
68 return sn_config->nodes;
74 return sn_config->cpus;
77 /* For SN, get the index th nasid */
82 return sn_memmap[index].nasid ;
86 GetMemBankInfo(int index)
88 return sn_memmap[index].node_memmap ;
92 IsCpuPresent(int cnode, int cpu)
94 return sn_memmap[cnode].cpuconfig & (1UL<<cpu);
99 * Made this into an explicit case statement so that
100 * we can assign specific properties to banks like bank0
101 * actually disabled etc.
106 IsBankPresent(int index, node_memmap_t nmemmap)
109 case 0:return BankPresent(nmemmap.b0size);
110 case 1:return BankPresent(nmemmap.b1size);
111 case 2:return BankPresent(nmemmap.b2size);
112 case 3:return BankPresent(nmemmap.b3size);
118 GetBankSize(int index, node_memmap_t nmemmap)
121 * Add 2 because there are 4 dimms per bank.
124 case 0:return 2 + ((long)nmemmap.b0size + nmemmap.b0dou);
125 case 1:return 2 + ((long)nmemmap.b1size + nmemmap.b1dou);
126 case 2:return 2 + ((long)nmemmap.b2size + nmemmap.b2dou);
127 case 3:return 2 + ((long)nmemmap.b3size + nmemmap.b3dou);
135 build_mem_desc(efi_memory_desc_t *md, int type, long paddr, long numbytes, long attr)
138 md->phys_addr = paddr;
140 md->num_pages = numbytes >> 12;
141 md->attribute = attr;
145 build_efi_memmap(void *md, int mdsize)
147 int numnodes = GetNumNodes() ;
150 node_memmap_t membank_info ;
153 long paddr, hole, numbytes;
156 for (cnode=0;cnode<numnodes;cnode++) {
157 nasid = GetNasid(cnode) ;
158 membank_info = GetMemBankInfo(cnode) ;
159 for (bank=0;bank<MD_BANKS_PER_NODE;bank++) {
160 if (IsBankPresent(bank, membank_info)) {
161 bsize = GetBankSize(bank, membank_info) ;
162 paddr = PHYS_ADDRESS(nasid, (long)bank<<MD_BANK_SHFT);
163 numbytes = BankSizeBytes(bsize);
167 * Shorten memory chunk by 1 page - makes a better
168 * testcase & is more like the real PROM.
170 numbytes = numbytes * 31 / 32;
173 * Only emulate the memory prom grabs
174 * if we have lots of memory, to allow
175 * us to simulate smaller memory configs than
176 * we can actually run on h/w. Otherwise,
177 * linux throws away a whole "granule".
179 if (cnode == 0 && bank == 0 &&
180 numbytes > 128*1024*1024) {
185 * Check for the node 0 hole. Since banks cant
186 * span the hole, we only need to check if the end of
187 * the range is the end of the hole.
189 if (paddr+numbytes == NODE0_HOLE_END)
190 numbytes -= NODE0_HOLE_SIZE;
192 * UGLY hack - we must skip overr the kernel and
193 * PROM runtime services but we dont exactly where it is.
194 * So lets just reserve:
204 build_mem_desc(md, EFI_PAL_CODE, paddr, hole, EFI_MEMORY_WB|EFI_MEMORY_WB);
210 build_mem_desc(md, EFI_CONVENTIONAL_MEMORY, paddr, hole, EFI_MEMORY_UC);
216 build_mem_desc(md, EFI_RUNTIME_SERVICES_DATA, paddr, hole, EFI_MEMORY_WB|EFI_MEMORY_WB);
223 build_mem_desc(md, EFI_RUNTIME_SERVICES_DATA, paddr, hole, EFI_MEMORY_WB|EFI_MEMORY_WB);
229 build_mem_desc(md, EFI_RUNTIME_SERVICES_DATA, paddr, hole, EFI_MEMORY_UC);
236 build_mem_desc(md, EFI_CONVENTIONAL_MEMORY, paddr, numbytes, EFI_MEMORY_WB|EFI_MEMORY_WB);
247 build_init(unsigned long args)
249 sn_config = (sn_config_t *) (args);
250 sn_memmap = (sn_memmap_t *)(args + 8) ; /* SN equiv for this is */
251 /* init to klconfig start */