Print this page
NEX-16819 loader UEFI support
Includes work by Toomas Soome <tsoome@me.com>
Upstream commits:
loader: pxe receive cleanup
9475 libefi: Do not return only if ReceiveFilter
installboot: should support efi system partition
8931 boot1.efi: scan all display modes rather than
loader: spinconsole updates
loader: gfx experiment to try GOP Blt() function.
sha1 build test
loader: add sha1 hash calculation
common/sha1: update for loader build
loader: biosdisk rework
uts: 32-bit kernel FB needs mapping in low memory
uts: add diag-device
uts: boot console mirror with diag-device
uts: enable very early console on ttya
kmdb: add diag-device as input/output device
uts: test VGA memory exclusion from mapping
uts: clear boot mapping and protect boot pages test
uts: add dboot map debug printf
uts: need to release FB pages in release_bootstrap()
uts: add screenmap ioctl
uts: update sys/queue.h
loader: add illumos uts/common to include path
loader: tem/gfx font cleanup
loader: vbe checks
uts: gfx_private set KD_TEXT when KD_RESETTEXT is
uts: gfx 8-bit update
loader: gfx 8-bit fix
loader: always set media size from partition.
uts: MB2 support for 32-bit kernel
loader: x86 should have tem 80x25
uts: x86 should have tem 80x25
uts: font update
loader: font update
uts: tem attributes
loader: tem.c comment added
uts: use font module
loader: add font module
loader: build rules for new font setup
uts: gfx_private update for new font structure
uts: early boot update for new font structure
uts: font update
uts: font build rules update for new fonts
uts: tem update to new font structure
loader: module.c needs to include tem_impl.h
uts: gfx_private 8x16 font rework
uts: make font_lookup public
loader: font rework
uts: font rework
9259 libefi: efi_alloc_and_read should check for PMBR
uts: tem utf-8 support
loader: implement tem utf-8 support
loader: tem should be able to display UTF-8
7784 uts: console input should support utf-8
7796 uts: ldterm default to utf-8
uts: do not reset serial console
uts: set up colors even if tem is not console
uts: add type for early boot properties
uts: gfx_private experiment with drm and vga
uts: gfx_private should use setmode drm callback.
uts: identify FB types and set up gfx_private based
loader: replace gop and vesa with framebuffer
uts: boot needs simple tem to support mdb
uts: boot_keyboard should emit esc sequences for
uts: gfx_private FB showuld be written by line
kmdb: set terminal window size
uts: gfx_private needs to keep track of early boot FB
pnglite: move pnglite to usr/src/common
loader: gfx_fb
ficl-sys: add gfx primitives
loader: add illumos.png logo
ficl: add fb-putimage
loader: add png support
loader: add alpha blending for gfx_fb
loader: use term-drawrect for menu frame
ficl: add simple gfx words
uts: provide fb_info via fbgattr dev_specific array.
uts: gfx_private add alpha blending
uts: update sys/ascii.h
uts: tem OSC support (incomplete)
uts: implement env module support and use data from
uts: tem get colors from early boot data
loader: use crc32 from libstand (libz)
loader: optimize for size
loader: pass tem info to the environment
loader: import tem for loader console
loader: UEFI loader needs to set ISADIR based on
loader: need UEFI32 support
8918 loader.efi: add vesa edid support
uts: tem_safe_pix_clear_prom_output() should only
uts: tem_safe_pix_clear_entire_screen() should use
uts: tem_safe_check_first_time() should query cursor
uts: tem implement cls callback & visual_io v4
uts: gfx_vgatext use block cursor for vgatext
uts: gfx_private implement cls callback & visual_io
uts: gfx_private bitmap framebuffer implementation
uts: early start frame buffer console support
uts: font functions should check the input char
uts: font rendering should support 16/24/32bit depths
uts: use smallest font as fallback default.
uts: update terminal dimensions based on selected
7834 uts: vgatext should use gfx_private
uts: add spacing property to 8859-1.bdf
terminfo: add underline for sun-color
terminfo: sun-color has 16 colors
uts: add font load callback type
loader: do not repeat int13 calls with error 0x20 and
8905 loader: add skein/edonr support
8904 common/crypto: make skein and edonr loader
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Revert "NEX-16819 loader UEFI support"
This reverts commit ec06b9fc617b99234e538bf2e7e4d02a24993e0c.
Reverting due to failures in the zfs-tests and the sharefs-tests
NEX-16819 loader UEFI support
Includes work by Toomas Soome <tsoome@me.com>
Upstream commits:
loader: pxe receive cleanup
9475 libefi: Do not return only if ReceiveFilter
installboot: should support efi system partition
8931 boot1.efi: scan all display modes rather than
loader: spinconsole updates
loader: gfx experiment to try GOP Blt() function.
sha1 build test
loader: add sha1 hash calculation
common/sha1: update for loader build
loader: biosdisk rework
uts: 32-bit kernel FB needs mapping in low memory
uts: add diag-device
uts: boot console mirror with diag-device
uts: enable very early console on ttya
kmdb: add diag-device as input/output device
uts: test VGA memory exclusion from mapping
uts: clear boot mapping and protect boot pages test
uts: add dboot map debug printf
uts: need to release FB pages in release_bootstrap()
uts: add screenmap ioctl
uts: update sys/queue.h
loader: add illumos uts/common to include path
loader: tem/gfx font cleanup
loader: vbe checks
uts: gfx_private set KD_TEXT when KD_RESETTEXT is
uts: gfx 8-bit update
loader: gfx 8-bit fix
loader: always set media size from partition.
uts: MB2 support for 32-bit kernel
loader: x86 should have tem 80x25
uts: x86 should have tem 80x25
uts: font update
loader: font update
uts: tem attributes
loader: tem.c comment added
uts: use font module
loader: add font module
loader: build rules for new font setup
uts: gfx_private update for new font structure
uts: early boot update for new font structure
uts: font update
uts: font build rules update for new fonts
uts: tem update to new font structure
loader: module.c needs to include tem_impl.h
uts: gfx_private 8x16 font rework
uts: make font_lookup public
loader: font rework
uts: font rework
libefi: efi_alloc_and_read should check for PMBR
uts: tem utf-8 support
loader: implement tem utf-8 support
loader: tem should be able to display UTF-8
7784 uts: console input should support utf-8
7796 uts: ldterm default to utf-8
uts: do not reset serial console
uts: set up colors even if tem is not console
uts: add type for early boot properties
uts: gfx_private experiment with drm and vga
uts: gfx_private should use setmode drm callback.
uts: identify FB types and set up gfx_private based
loader: replace gop and vesa with framebuffer
uts: boot needs simple tem to support mdb
uts: boot_keyboard should emit esc sequences for
uts: gfx_private FB showuld be written by line
kmdb: set terminal window size
uts: gfx_private needs to keep track of early boot FB
pnglite: move pnglite to usr/src/common
loader: gfx_fb
ficl-sys: add gfx primitives
loader: add illumos.png logo
ficl: add fb-putimage
loader: add png support
loader: add alpha blending for gfx_fb
loader: use term-drawrect for menu frame
ficl: add simple gfx words
uts: provide fb_info via fbgattr dev_specific array.
uts: gfx_private add alpha blending
uts: update sys/ascii.h
uts: tem OSC support (incomplete)
uts: implement env module support and use data from
uts: tem get colors from early boot data
loader: use crc32 from libstand (libz)
loader: optimize for size
loader: pass tem info to the environment
loader: import tem for loader console
loader: UEFI loader needs to set ISADIR based on
loader: need UEFI32 support
8918 loader.efi: add vesa edid support
uts: tem_safe_pix_clear_prom_output() should only
uts: tem_safe_pix_clear_entire_screen() should use
uts: tem_safe_check_first_time() should query cursor
uts: tem implement cls callback & visual_io v4
uts: gfx_vgatext use block cursor for vgatext
uts: gfx_private implement cls callback & visual_io
uts: gfx_private bitmap framebuffer implementation
uts: early start frame buffer console support
uts: font functions should check the input char
uts: font rendering should support 16/24/32bit depths
uts: use smallest font as fallback default.
uts: update terminal dimensions based on selected
7834 uts: vgatext should use gfx_private
uts: add spacing property to 8859-1.bdf
terminfo: add underline for sun-color
terminfo: sun-color has 16 colors
uts: add font load callback type
loader: do not repeat int13 calls with error 0x20 and
8905 loader: add skein/edonr support
8904 common/crypto: make skein and edonr loader
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/i86pc/os/fakebop.c
+++ new/usr/src/uts/i86pc/os/fakebop.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 *
26 26 * Copyright (c) 2010, Intel Corporation.
27 27 * All rights reserved.
28 28 *
29 29 * Copyright 2013 Joyent, Inc. All rights reserved.
30 30 */
31 31
32 32 /*
33 33 * This file contains the functionality that mimics the boot operations
34 34 * on SPARC systems or the old boot.bin/multiboot programs on x86 systems.
35 35 * The x86 kernel now does everything on its own.
36 36 */
37 37
38 38 #include <sys/types.h>
39 39 #include <sys/bootconf.h>
40 40 #include <sys/bootsvcs.h>
41 41 #include <sys/bootinfo.h>
42 42 #include <sys/multiboot.h>
|
↓ open down ↓ |
42 lines elided |
↑ open up ↑ |
43 43 #include <sys/multiboot2.h>
44 44 #include <sys/multiboot2_impl.h>
45 45 #include <sys/bootvfs.h>
46 46 #include <sys/bootprops.h>
47 47 #include <sys/varargs.h>
48 48 #include <sys/param.h>
49 49 #include <sys/machparam.h>
50 50 #include <sys/machsystm.h>
51 51 #include <sys/archsystm.h>
52 52 #include <sys/boot_console.h>
53 +#include <sys/framebuffer.h>
53 54 #include <sys/cmn_err.h>
54 55 #include <sys/systm.h>
55 56 #include <sys/promif.h>
56 57 #include <sys/archsystm.h>
57 58 #include <sys/x86_archext.h>
58 59 #include <sys/kobj.h>
59 60 #include <sys/privregs.h>
60 61 #include <sys/sysmacros.h>
61 62 #include <sys/ctype.h>
62 63 #include <sys/fastboot.h>
63 64 #ifdef __xpv
64 65 #include <sys/hypervisor.h>
|
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
65 66 #include <net/if.h>
66 67 #endif
67 68 #include <vm/kboot_mmu.h>
68 69 #include <vm/hat_pte.h>
69 70 #include <sys/kobj.h>
70 71 #include <sys/kobj_lex.h>
71 72 #include <sys/pci_cfgspace_impl.h>
72 73 #include <sys/fastboot_impl.h>
73 74 #include <sys/acpi/acconfig.h>
74 75 #include <sys/acpi/acpi.h>
76 +#include <sys/ddipropdefs.h> /* For DDI prop types */
75 77
76 78 static int have_console = 0; /* set once primitive console is initialized */
77 79 static char *boot_args = "";
78 80
79 81 /*
80 82 * Debugging macros
81 83 */
82 84 static uint_t kbm_debug = 0;
83 85 #define DBG_MSG(s) { if (kbm_debug) bop_printf(NULL, "%s", s); }
84 86 #define DBG(x) { if (kbm_debug) \
85 87 bop_printf(NULL, "%s is %" PRIx64 "\n", #x, (uint64_t)(x)); \
86 88 }
87 89
88 90 #define PUT_STRING(s) { \
89 91 char *cp; \
90 92 for (cp = (s); *cp; ++cp) \
91 93 bcons_putchar(*cp); \
92 94 }
93 95
96 +/* callback to boot_fb to set shadow frame buffer */
97 +extern void boot_fb_shadow_init(bootops_t *);
98 +
94 99 bootops_t bootop; /* simple bootops we'll pass on to kernel */
95 100 struct bsys_mem bm;
96 101
97 102 /*
98 103 * Boot info from "glue" code in low memory. xbootp is used by:
99 104 * do_bop_phys_alloc(), do_bsys_alloc() and boot_prop_finish().
100 105 */
101 106 static struct xboot_info *xbootp;
102 107 static uintptr_t next_virt; /* next available virtual address */
103 108 static paddr_t next_phys; /* next available physical address from dboot */
104 109 static paddr_t high_phys = -(paddr_t)1; /* last used physical address */
105 110
106 111 /*
107 112 * buffer for vsnprintf for console I/O
|
↓ open down ↓ |
4 lines elided |
↑ open up ↑ |
108 113 */
109 114 #define BUFFERSIZE 512
110 115 static char buffer[BUFFERSIZE];
111 116
112 117 /*
113 118 * stuff to store/report/manipulate boot property settings.
114 119 */
115 120 typedef struct bootprop {
116 121 struct bootprop *bp_next;
117 122 char *bp_name;
118 - uint_t bp_vlen;
123 + int bp_flags; /* DDI prop type */
124 + uint_t bp_vlen; /* 0 for boolean */
119 125 char *bp_value;
120 126 } bootprop_t;
121 127
122 128 static bootprop_t *bprops = NULL;
123 129 static char *curr_page = NULL; /* ptr to avail bprop memory */
124 130 static int curr_space = 0; /* amount of memory at curr_page */
125 131
126 132 #ifdef __xpv
127 133 start_info_t *xen_info;
128 134 shared_info_t *HYPERVISOR_shared_info;
129 135 #endif
130 136
131 137 /*
132 138 * some allocator statistics
133 139 */
134 140 static ulong_t total_bop_alloc_scratch = 0;
135 141 static ulong_t total_bop_alloc_kernel = 0;
136 142
137 143 static void build_firmware_properties(struct xboot_info *);
138 144
139 145 static int early_allocation = 1;
140 146
141 147 int force_fastreboot = 0;
142 148 volatile int fastreboot_onpanic = 0;
143 149 int post_fastreboot = 0;
144 150 #ifdef __xpv
145 151 volatile int fastreboot_capable = 0;
146 152 #else
147 153 volatile int fastreboot_capable = 1;
148 154 #endif
149 155
150 156 /*
151 157 * Information saved from current boot for fast reboot.
152 158 * If the information size exceeds what we have allocated, fast reboot
153 159 * will not be supported.
154 160 */
155 161 multiboot_info_t saved_mbi;
156 162 mb_memory_map_t saved_mmap[FASTBOOT_SAVED_MMAP_COUNT];
157 163 uint8_t saved_drives[FASTBOOT_SAVED_DRIVES_SIZE];
158 164 char saved_cmdline[FASTBOOT_SAVED_CMDLINE_LEN];
159 165 int saved_cmdline_len = 0;
160 166 size_t saved_file_size[FASTBOOT_MAX_FILES_MAP];
161 167
162 168 /*
163 169 * Turn off fastreboot_onpanic to avoid panic loop.
164 170 */
165 171 char fastreboot_onpanic_cmdline[FASTBOOT_SAVED_CMDLINE_LEN];
166 172 static const char fastreboot_onpanic_args[] = " -B fastreboot_onpanic=0";
167 173
168 174 /*
169 175 * Pointers to where System Resource Affinity Table (SRAT), System Locality
170 176 * Information Table (SLIT) and Maximum System Capability Table (MSCT)
171 177 * are mapped into virtual memory
172 178 */
173 179 ACPI_TABLE_SRAT *srat_ptr = NULL;
174 180 ACPI_TABLE_SLIT *slit_ptr = NULL;
175 181 ACPI_TABLE_MSCT *msct_ptr = NULL;
176 182
177 183 /*
178 184 * Arbitrary limit on number of localities we handle; if
179 185 * this limit is raised to more than UINT16_MAX, make sure
180 186 * process_slit() knows how to handle it.
181 187 */
182 188 #define SLIT_LOCALITIES_MAX (4096)
183 189
184 190 #define SLIT_NUM_PROPNAME "acpi-slit-localities"
185 191 #define SLIT_PROPNAME "acpi-slit"
186 192
187 193 /*
188 194 * Allocate aligned physical memory at boot time. This allocator allocates
189 195 * from the highest possible addresses. This avoids exhausting memory that
190 196 * would be useful for DMA buffers.
191 197 */
192 198 paddr_t
193 199 do_bop_phys_alloc(uint64_t size, uint64_t align)
194 200 {
195 201 paddr_t pa = 0;
196 202 paddr_t start;
197 203 paddr_t end;
198 204 struct memlist *ml = (struct memlist *)xbootp->bi_phys_install;
199 205
200 206 /*
201 207 * Be careful if high memory usage is limited in startup.c
202 208 * Since there are holes in the low part of the physical address
203 209 * space we can treat physmem as a pfn (not just a pgcnt) and
204 210 * get a conservative upper limit.
205 211 */
206 212 if (physmem != 0 && high_phys > pfn_to_pa(physmem))
207 213 high_phys = pfn_to_pa(physmem);
208 214
209 215 /*
210 216 * find the highest available memory in physinstalled
211 217 */
212 218 size = P2ROUNDUP(size, align);
213 219 for (; ml; ml = ml->ml_next) {
214 220 start = P2ROUNDUP(ml->ml_address, align);
215 221 end = P2ALIGN(ml->ml_address + ml->ml_size, align);
216 222 if (start < next_phys)
217 223 start = P2ROUNDUP(next_phys, align);
218 224 if (end > high_phys)
219 225 end = P2ALIGN(high_phys, align);
220 226
221 227 if (end <= start)
222 228 continue;
223 229 if (end - start < size)
224 230 continue;
225 231
226 232 /*
227 233 * Early allocations need to use low memory, since
228 234 * physmem might be further limited by bootenv.rc
229 235 */
230 236 if (early_allocation) {
231 237 if (pa == 0 || start < pa)
232 238 pa = start;
233 239 } else {
234 240 if (end - size > pa)
235 241 pa = end - size;
236 242 }
237 243 }
238 244 if (pa != 0) {
239 245 if (early_allocation)
240 246 next_phys = pa + size;
241 247 else
242 248 high_phys = pa;
243 249 return (pa);
244 250 }
245 251 bop_panic("do_bop_phys_alloc(0x%" PRIx64 ", 0x%" PRIx64
246 252 ") Out of memory\n", size, align);
247 253 /*NOTREACHED*/
248 254 }
249 255
250 256 uintptr_t
251 257 alloc_vaddr(size_t size, paddr_t align)
252 258 {
253 259 uintptr_t rv;
254 260
255 261 next_virt = P2ROUNDUP(next_virt, (uintptr_t)align);
256 262 rv = (uintptr_t)next_virt;
257 263 next_virt += size;
258 264 return (rv);
259 265 }
260 266
261 267 /*
262 268 * Allocate virtual memory. The size is always rounded up to a multiple
263 269 * of base pagesize.
264 270 */
265 271
266 272 /*ARGSUSED*/
267 273 static caddr_t
268 274 do_bsys_alloc(bootops_t *bop, caddr_t virthint, size_t size, int align)
269 275 {
270 276 paddr_t a = align; /* same type as pa for masking */
271 277 uint_t pgsize;
272 278 paddr_t pa;
273 279 uintptr_t va;
274 280 ssize_t s; /* the aligned size */
275 281 uint_t level;
276 282 uint_t is_kernel = (virthint != 0);
277 283
278 284 if (a < MMU_PAGESIZE)
279 285 a = MMU_PAGESIZE;
280 286 else if (!ISP2(a))
281 287 prom_panic("do_bsys_alloc() incorrect alignment");
282 288 size = P2ROUNDUP(size, MMU_PAGESIZE);
283 289
284 290 /*
285 291 * Use the next aligned virtual address if we weren't given one.
286 292 */
287 293 if (virthint == NULL) {
288 294 virthint = (caddr_t)alloc_vaddr(size, a);
289 295 total_bop_alloc_scratch += size;
290 296 } else {
291 297 total_bop_alloc_kernel += size;
292 298 }
293 299
294 300 /*
295 301 * allocate the physical memory
296 302 */
297 303 pa = do_bop_phys_alloc(size, a);
298 304
299 305 /*
300 306 * Add the mappings to the page tables, try large pages first.
301 307 */
302 308 va = (uintptr_t)virthint;
303 309 s = size;
304 310 level = 1;
305 311 pgsize = xbootp->bi_use_pae ? TWO_MEG : FOUR_MEG;
306 312 if (xbootp->bi_use_largepage && a == pgsize) {
307 313 while (IS_P2ALIGNED(pa, pgsize) && IS_P2ALIGNED(va, pgsize) &&
308 314 s >= pgsize) {
309 315 kbm_map(va, pa, level, is_kernel);
310 316 va += pgsize;
311 317 pa += pgsize;
312 318 s -= pgsize;
313 319 }
314 320 }
315 321
316 322 /*
317 323 * Map remaining pages use small mappings
318 324 */
319 325 level = 0;
320 326 pgsize = MMU_PAGESIZE;
321 327 while (s > 0) {
322 328 kbm_map(va, pa, level, is_kernel);
323 329 va += pgsize;
324 330 pa += pgsize;
325 331 s -= pgsize;
326 332 }
327 333 return (virthint);
328 334 }
329 335
330 336 /*
331 337 * Free virtual memory - we'll just ignore these.
332 338 */
333 339 /*ARGSUSED*/
334 340 static void
335 341 do_bsys_free(bootops_t *bop, caddr_t virt, size_t size)
336 342 {
337 343 bop_printf(NULL, "do_bsys_free(virt=0x%p, size=0x%lx) ignored\n",
338 344 (void *)virt, size);
339 345 }
340 346
341 347 /*
342 348 * Old interface
343 349 */
344 350 /*ARGSUSED*/
|
↓ open down ↓ |
216 lines elided |
↑ open up ↑ |
345 351 static caddr_t
346 352 do_bsys_ealloc(bootops_t *bop, caddr_t virthint, size_t size,
347 353 int align, int flags)
348 354 {
349 355 prom_panic("unsupported call to BOP_EALLOC()\n");
350 356 return (0);
351 357 }
352 358
353 359
354 360 static void
355 -bsetprop(char *name, int nlen, void *value, int vlen)
361 +bsetprop(int flags, char *name, int nlen, void *value, int vlen)
356 362 {
357 363 uint_t size;
358 364 uint_t need_size;
359 365 bootprop_t *b;
360 366
361 367 /*
362 368 * align the size to 16 byte boundary
363 369 */
364 370 size = sizeof (bootprop_t) + nlen + 1 + vlen;
365 371 size = (size + 0xf) & ~0xf;
366 372 if (size > curr_space) {
367 373 need_size = (size + (MMU_PAGEOFFSET)) & MMU_PAGEMASK;
368 374 curr_page = do_bsys_alloc(NULL, 0, need_size, MMU_PAGESIZE);
369 375 curr_space = need_size;
370 376 }
371 377
372 378 /*
373 379 * use a bootprop_t at curr_page and link into list
374 380 */
375 381 b = (bootprop_t *)curr_page;
376 382 curr_page += sizeof (bootprop_t);
377 383 curr_space -= sizeof (bootprop_t);
378 384 b->bp_next = bprops;
379 385 bprops = b;
380 386
|
↓ open down ↓ |
15 lines elided |
↑ open up ↑ |
381 387 /*
382 388 * follow by name and ending zero byte
383 389 */
384 390 b->bp_name = curr_page;
385 391 bcopy(name, curr_page, nlen);
386 392 curr_page += nlen;
387 393 *curr_page++ = 0;
388 394 curr_space -= nlen + 1;
389 395
390 396 /*
397 + * set the property type
398 + */
399 + b->bp_flags = flags & DDI_PROP_TYPE_MASK;
400 +
401 + /*
391 402 * copy in value, but no ending zero byte
392 403 */
393 404 b->bp_value = curr_page;
394 405 b->bp_vlen = vlen;
395 406 if (vlen > 0) {
396 407 bcopy(value, curr_page, vlen);
397 408 curr_page += vlen;
398 409 curr_space -= vlen;
399 410 }
400 411
401 412 /*
402 413 * align new values of curr_page, curr_space
|
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
403 414 */
404 415 while (curr_space & 0xf) {
405 416 ++curr_page;
406 417 --curr_space;
407 418 }
408 419 }
409 420
410 421 static void
411 422 bsetprops(char *name, char *value)
412 423 {
413 - bsetprop(name, strlen(name), value, strlen(value) + 1);
424 + bsetprop(DDI_PROP_TYPE_STRING, name, strlen(name),
425 + value, strlen(value) + 1);
414 426 }
415 427
416 428 static void
429 +bsetprop32(char *name, uint32_t value)
430 +{
431 + bsetprop(DDI_PROP_TYPE_INT, name, strlen(name),
432 + (void *)&value, sizeof (value));
433 +}
434 +
435 +static void
417 436 bsetprop64(char *name, uint64_t value)
418 437 {
419 - bsetprop(name, strlen(name), (void *)&value, sizeof (value));
438 + bsetprop(DDI_PROP_TYPE_INT64, name, strlen(name),
439 + (void *)&value, sizeof (value));
420 440 }
421 441
422 442 static void
423 443 bsetpropsi(char *name, int value)
424 444 {
425 445 char prop_val[32];
426 446
427 447 (void) snprintf(prop_val, sizeof (prop_val), "%d", value);
428 448 bsetprops(name, prop_val);
429 449 }
430 450
431 451 /*
452 + * to find the type of the value associated with this name
453 + */
454 +/*ARGSUSED*/
455 +int
456 +do_bsys_getproptype(bootops_t *bop, const char *name)
457 +{
458 + bootprop_t *b;
459 +
460 + for (b = bprops; b; b = b->bp_next) {
461 + if (strcmp(name, b->bp_name) != 0)
462 + continue;
463 + return (b->bp_flags);
464 + }
465 + return (-1);
466 +}
467 +
468 +/*
432 469 * to find the size of the buffer to allocate
433 470 */
434 471 /*ARGSUSED*/
435 472 int
436 473 do_bsys_getproplen(bootops_t *bop, const char *name)
437 474 {
438 475 bootprop_t *b;
439 476
440 477 for (b = bprops; b; b = b->bp_next) {
441 478 if (strcmp(name, b->bp_name) != 0)
442 479 continue;
443 480 return (b->bp_vlen);
444 481 }
445 482 return (-1);
446 483 }
447 484
448 485 /*
449 486 * get the value associated with this name
450 487 */
451 488 /*ARGSUSED*/
452 489 int
453 490 do_bsys_getprop(bootops_t *bop, const char *name, void *value)
454 491 {
455 492 bootprop_t *b;
456 493
457 494 for (b = bprops; b; b = b->bp_next) {
458 495 if (strcmp(name, b->bp_name) != 0)
459 496 continue;
460 497 bcopy(b->bp_value, value, b->bp_vlen);
461 498 return (0);
462 499 }
463 500 return (-1);
464 501 }
465 502
466 503 /*
467 504 * get the name of the next property in succession from the standalone
468 505 */
469 506 /*ARGSUSED*/
470 507 static char *
471 508 do_bsys_nextprop(bootops_t *bop, char *name)
472 509 {
473 510 bootprop_t *b;
474 511
475 512 /*
476 513 * A null name is a special signal for the 1st boot property
477 514 */
478 515 if (name == NULL || strlen(name) == 0) {
479 516 if (bprops == NULL)
480 517 return (NULL);
481 518 return (bprops->bp_name);
482 519 }
483 520
484 521 for (b = bprops; b; b = b->bp_next) {
485 522 if (name != b->bp_name)
486 523 continue;
487 524 b = b->bp_next;
488 525 if (b == NULL)
489 526 return (NULL);
490 527 return (b->bp_name);
491 528 }
492 529 return (NULL);
493 530 }
494 531
495 532 /*
496 533 * Parse numeric value from a string. Understands decimal, hex, octal, - and ~
497 534 */
498 535 static int
499 536 parse_value(char *p, uint64_t *retval)
500 537 {
501 538 int adjust = 0;
502 539 uint64_t tmp = 0;
503 540 int digit;
504 541 int radix = 10;
505 542
506 543 *retval = 0;
507 544 if (*p == '-' || *p == '~')
508 545 adjust = *p++;
509 546
510 547 if (*p == '0') {
511 548 ++p;
512 549 if (*p == 0)
513 550 return (0);
514 551 if (*p == 'x' || *p == 'X') {
515 552 radix = 16;
516 553 ++p;
517 554 } else {
518 555 radix = 8;
519 556 ++p;
520 557 }
521 558 }
522 559 while (*p) {
523 560 if ('0' <= *p && *p <= '9')
524 561 digit = *p - '0';
525 562 else if ('a' <= *p && *p <= 'f')
526 563 digit = 10 + *p - 'a';
527 564 else if ('A' <= *p && *p <= 'F')
528 565 digit = 10 + *p - 'A';
529 566 else
530 567 return (-1);
531 568 if (digit >= radix)
532 569 return (-1);
533 570 tmp = tmp * radix + digit;
534 571 ++p;
535 572 }
536 573 if (adjust == '-')
537 574 tmp = -tmp;
538 575 else if (adjust == '~')
539 576 tmp = ~tmp;
540 577 *retval = tmp;
541 578 return (0);
542 579 }
543 580
544 581 static boolean_t
545 582 unprintable(char *value, int size)
546 583 {
547 584 int i;
548 585
549 586 if (size <= 0 || value[0] == '\0')
550 587 return (B_TRUE);
551 588
552 589 for (i = 0; i < size; i++) {
553 590 if (value[i] == '\0')
554 591 return (i != (size - 1));
555 592
556 593 if (!isprint(value[i]))
557 594 return (B_TRUE);
558 595 }
559 596 return (B_FALSE);
560 597 }
|
↓ open down ↓ |
119 lines elided |
↑ open up ↑ |
561 598
562 599 /*
563 600 * Print out information about all boot properties.
564 601 * buffer is pointer to pre-allocated space to be used as temporary
565 602 * space for property values.
566 603 */
567 604 static void
568 605 boot_prop_display(char *buffer)
569 606 {
570 607 char *name = "";
571 - int i, len;
608 + int i, len, flags, *buf32;
609 + uint64_t *buf64;
572 610
573 611 bop_printf(NULL, "\nBoot properties:\n");
574 612
575 613 while ((name = do_bsys_nextprop(NULL, name)) != NULL) {
576 614 bop_printf(NULL, "\t0x%p %s = ", (void *)name, name);
577 615 (void) do_bsys_getprop(NULL, name, buffer);
578 616 len = do_bsys_getproplen(NULL, name);
617 + flags = do_bsys_getproptype(NULL, name);
579 618 bop_printf(NULL, "len=%d ", len);
580 - if (!unprintable(buffer, len)) {
581 - buffer[len] = 0;
582 - bop_printf(NULL, "%s\n", buffer);
583 - continue;
619 +
620 + switch (flags) {
621 + case DDI_PROP_TYPE_INT:
622 + len = len / sizeof (int);
623 + buf32 = (int *)buffer;
624 + for (i = 0; i < len; i++) {
625 + bop_printf(NULL, "%08x", buf32[i]);
626 + if (i < len - 1)
627 + bop_printf(NULL, ".");
628 + }
629 + break;
630 + case DDI_PROP_TYPE_STRING:
631 + bop_printf(NULL, buffer);
632 + break;
633 + case DDI_PROP_TYPE_INT64:
634 + len = len / sizeof (uint64_t);
635 + buf64 = (uint64_t *)buffer;
636 + for (i = 0; i < len; i++) {
637 + bop_printf(NULL, "%016" PRIx64, buf64[i]);
638 + if (i < len - 1)
639 + bop_printf(NULL, ".");
640 + }
641 + break;
642 + default:
643 + if (!unprintable(buffer, len)) {
644 + buffer[len] = 0;
645 + bop_printf(NULL, "%s", buffer);
646 + break;
647 + }
648 + for (i = 0; i < len; i++) {
649 + bop_printf(NULL, "%02x", buffer[i] & 0xff);
650 + if (i < len - 1)
651 + bop_printf(NULL, ".");
652 + }
653 + break;
584 654 }
585 - for (i = 0; i < len; i++) {
586 - bop_printf(NULL, "%02x", buffer[i] & 0xff);
587 - if (i < len - 1)
588 - bop_printf(NULL, ".");
589 - }
590 655 bop_printf(NULL, "\n");
591 656 }
592 657 }
593 658
594 659 /*
595 660 * 2nd part of building the table of boot properties. This includes:
596 661 * - values from /boot/solaris/bootenv.rc (ie. eeprom(1m) values)
597 662 *
598 663 * lines look like one of:
599 664 * ^$
600 665 * ^# comment till end of line
601 666 * setprop name 'value'
602 667 * setprop name value
603 668 * setprop name "value"
604 669 *
605 670 * we do single character I/O since this is really just looking at memory
606 671 */
607 672 void
608 673 boot_prop_finish(void)
609 674 {
610 675 int fd;
611 676 char *line;
612 677 int c;
613 678 int bytes_read;
614 679 char *name;
615 680 int n_len;
616 681 char *value;
617 682 int v_len;
618 683 char *inputdev; /* these override the command line if serial ports */
619 684 char *outputdev;
620 685 char *consoledev;
621 686 uint64_t lvalue;
622 687 int use_xencons = 0;
623 688
624 689 #ifdef __xpv
625 690 if (!DOMAIN_IS_INITDOMAIN(xen_info))
626 691 use_xencons = 1;
627 692 #endif /* __xpv */
628 693
629 694 DBG_MSG("Opening /boot/solaris/bootenv.rc\n");
630 695 fd = BRD_OPEN(bfs_ops, "/boot/solaris/bootenv.rc", 0);
631 696 DBG(fd);
632 697
633 698 line = do_bsys_alloc(NULL, NULL, MMU_PAGESIZE, MMU_PAGESIZE);
634 699 while (fd >= 0) {
635 700
636 701 /*
637 702 * get a line
638 703 */
639 704 for (c = 0; ; ++c) {
640 705 bytes_read = BRD_READ(bfs_ops, fd, line + c, 1);
641 706 if (bytes_read == 0) {
642 707 if (c == 0)
643 708 goto done;
644 709 break;
645 710 }
646 711 if (line[c] == '\n')
647 712 break;
648 713 }
649 714 line[c] = 0;
650 715
651 716 /*
652 717 * ignore comment lines
653 718 */
654 719 c = 0;
655 720 while (ISSPACE(line[c]))
656 721 ++c;
657 722 if (line[c] == '#' || line[c] == 0)
658 723 continue;
659 724
660 725 /*
661 726 * must have "setprop " or "setprop\t"
662 727 */
663 728 if (strncmp(line + c, "setprop ", 8) != 0 &&
664 729 strncmp(line + c, "setprop\t", 8) != 0)
665 730 continue;
666 731 c += 8;
667 732 while (ISSPACE(line[c]))
668 733 ++c;
669 734 if (line[c] == 0)
670 735 continue;
671 736
672 737 /*
673 738 * gather up the property name
674 739 */
675 740 name = line + c;
676 741 n_len = 0;
677 742 while (line[c] && !ISSPACE(line[c]))
678 743 ++n_len, ++c;
679 744
680 745 /*
681 746 * gather up the value, if any
682 747 */
683 748 value = "";
684 749 v_len = 0;
685 750 while (ISSPACE(line[c]))
686 751 ++c;
687 752 if (line[c] != 0) {
688 753 value = line + c;
689 754 while (line[c] && !ISSPACE(line[c]))
690 755 ++v_len, ++c;
691 756 }
692 757
693 758 if (v_len >= 2 && value[0] == value[v_len - 1] &&
694 759 (value[0] == '\'' || value[0] == '"')) {
695 760 ++value;
696 761 v_len -= 2;
697 762 }
698 763 name[n_len] = 0;
699 764 if (v_len > 0)
700 765 value[v_len] = 0;
701 766 else
702 767 continue;
703 768
704 769 /*
705 770 * ignore "boot-file" property, it's now meaningless
706 771 */
|
↓ open down ↓ |
107 lines elided |
↑ open up ↑ |
707 772 if (strcmp(name, "boot-file") == 0)
708 773 continue;
709 774 if (strcmp(name, "boot-args") == 0 &&
710 775 strlen(boot_args) > 0)
711 776 continue;
712 777
713 778 /*
714 779 * If a property was explicitly set on the command line
715 780 * it will override a setting in bootenv.rc
716 781 */
717 - if (do_bsys_getproplen(NULL, name) > 0)
782 + if (do_bsys_getproplen(NULL, name) >= 0)
718 783 continue;
719 784
720 - bsetprop(name, n_len, value, v_len + 1);
785 + bsetprops(name, value);
721 786 }
722 787 done:
723 788 if (fd >= 0)
724 789 (void) BRD_CLOSE(bfs_ops, fd);
725 790
726 791 /*
727 792 * Check if we have to limit the boot time allocator
728 793 */
729 794 if (do_bsys_getproplen(NULL, "physmem") != -1 &&
730 795 do_bsys_getprop(NULL, "physmem", line) >= 0 &&
731 796 parse_value(line, &lvalue) != -1) {
732 797 if (0 < lvalue && (lvalue < physmem || physmem == 0)) {
733 798 physmem = (pgcnt_t)lvalue;
734 799 DBG(physmem);
735 800 }
736 801 }
737 802 early_allocation = 0;
738 803
739 804 /*
740 805 * check to see if we have to override the default value of the console
741 806 */
742 807 if (!use_xencons) {
743 808 inputdev = line;
744 809 v_len = do_bsys_getproplen(NULL, "input-device");
745 810 if (v_len > 0)
746 811 (void) do_bsys_getprop(NULL, "input-device", inputdev);
747 812 else
748 813 v_len = 0;
749 814 inputdev[v_len] = 0;
750 815
751 816 outputdev = inputdev + v_len + 1;
752 817 v_len = do_bsys_getproplen(NULL, "output-device");
753 818 if (v_len > 0)
754 819 (void) do_bsys_getprop(NULL, "output-device",
755 820 outputdev);
756 821 else
757 822 v_len = 0;
758 823 outputdev[v_len] = 0;
759 824
760 825 consoledev = outputdev + v_len + 1;
761 826 v_len = do_bsys_getproplen(NULL, "console");
762 827 if (v_len > 0) {
763 828 (void) do_bsys_getprop(NULL, "console", consoledev);
764 829 if (post_fastreboot &&
765 830 strcmp(consoledev, "graphics") == 0) {
766 831 bsetprops("console", "text");
767 832 v_len = strlen("text");
768 833 bcopy("text", consoledev, v_len);
769 834 }
770 835 } else {
771 836 v_len = 0;
772 837 }
773 838 consoledev[v_len] = 0;
774 839 bcons_init2(inputdev, outputdev, consoledev);
775 840 } else {
776 841 /*
777 842 * Ensure console property exists
778 843 * If not create it as "hypervisor"
779 844 */
780 845 v_len = do_bsys_getproplen(NULL, "console");
781 846 if (v_len < 0)
782 847 bsetprops("console", "hypervisor");
783 848 inputdev = outputdev = consoledev = "hypervisor";
784 849 bcons_init2(inputdev, outputdev, consoledev);
785 850 }
786 851
787 852 if (find_boot_prop("prom_debug") || kbm_debug)
788 853 boot_prop_display(line);
789 854 }
790 855
791 856 /*
792 857 * print formatted output
793 858 */
794 859 /*PRINTFLIKE2*/
795 860 /*ARGSUSED*/
796 861 void
797 862 bop_printf(bootops_t *bop, const char *fmt, ...)
798 863 {
799 864 va_list ap;
800 865
801 866 if (have_console == 0)
802 867 return;
803 868
804 869 va_start(ap, fmt);
805 870 (void) vsnprintf(buffer, BUFFERSIZE, fmt, ap);
806 871 va_end(ap);
807 872 PUT_STRING(buffer);
808 873 }
809 874
810 875 /*
811 876 * Another panic() variant; this one can be used even earlier during boot than
812 877 * prom_panic().
813 878 */
814 879 /*PRINTFLIKE1*/
815 880 void
816 881 bop_panic(const char *fmt, ...)
817 882 {
818 883 va_list ap;
819 884
820 885 va_start(ap, fmt);
821 886 bop_printf(NULL, fmt, ap);
822 887 va_end(ap);
823 888
824 889 bop_printf(NULL, "\nPress any key to reboot.\n");
825 890 (void) bcons_getchar();
826 891 bop_printf(NULL, "Resetting...\n");
827 892 pc_reset();
828 893 }
829 894
830 895 /*
831 896 * Do a real mode interrupt BIOS call
832 897 */
833 898 typedef struct bios_regs {
834 899 unsigned short ax, bx, cx, dx, si, di, bp, es, ds;
835 900 } bios_regs_t;
836 901 typedef int (*bios_func_t)(int, bios_regs_t *);
837 902
838 903 /*ARGSUSED*/
839 904 static void
840 905 do_bsys_doint(bootops_t *bop, int intnum, struct bop_regs *rp)
841 906 {
842 907 #if defined(__xpv)
843 908 prom_panic("unsupported call to BOP_DOINT()\n");
844 909 #else /* __xpv */
845 910 static int firsttime = 1;
846 911 bios_func_t bios_func = (bios_func_t)(void *)(uintptr_t)0x5000;
847 912 bios_regs_t br;
848 913
849 914 /*
850 915 * The first time we do this, we have to copy the pre-packaged
851 916 * low memory bios call code image into place.
852 917 */
853 918 if (firsttime) {
854 919 extern char bios_image[];
855 920 extern uint32_t bios_size;
856 921
857 922 bcopy(bios_image, (void *)bios_func, bios_size);
858 923 firsttime = 0;
859 924 }
860 925
861 926 br.ax = rp->eax.word.ax;
862 927 br.bx = rp->ebx.word.bx;
863 928 br.cx = rp->ecx.word.cx;
864 929 br.dx = rp->edx.word.dx;
865 930 br.bp = rp->ebp.word.bp;
866 931 br.si = rp->esi.word.si;
867 932 br.di = rp->edi.word.di;
868 933 br.ds = rp->ds;
869 934 br.es = rp->es;
870 935
871 936 DBG_MSG("Doing BIOS call...");
872 937 DBG(br.ax);
873 938 DBG(br.bx);
874 939 DBG(br.dx);
875 940 rp->eflags = bios_func(intnum, &br);
876 941 DBG_MSG("done\n");
877 942
878 943 rp->eax.word.ax = br.ax;
879 944 rp->ebx.word.bx = br.bx;
880 945 rp->ecx.word.cx = br.cx;
881 946 rp->edx.word.dx = br.dx;
882 947 rp->ebp.word.bp = br.bp;
883 948 rp->esi.word.si = br.si;
884 949 rp->edi.word.di = br.di;
885 950 rp->ds = br.ds;
886 951 rp->es = br.es;
887 952 #endif /* __xpv */
888 953 }
889 954
890 955 static struct boot_syscalls bop_sysp = {
891 956 bcons_getchar,
892 957 bcons_putchar,
893 958 bcons_ischar,
894 959 };
895 960
896 961 static char *whoami;
897 962
898 963 #define BUFLEN 64
899 964
900 965 #if defined(__xpv)
901 966
902 967 static char namebuf[32];
903 968
904 969 static void
905 970 xen_parse_props(char *s, char *prop_map[], int n_prop)
906 971 {
907 972 char **prop_name = prop_map;
908 973 char *cp = s, *scp;
909 974
910 975 do {
911 976 scp = cp;
912 977 while ((*cp != NULL) && (*cp != ':'))
913 978 cp++;
914 979
915 980 if ((scp != cp) && (*prop_name != NULL)) {
916 981 *cp = NULL;
917 982 bsetprops(*prop_name, scp);
918 983 }
919 984
920 985 cp++;
921 986 prop_name++;
922 987 n_prop--;
923 988 } while (n_prop > 0);
924 989 }
925 990
926 991 #define VBDPATHLEN 64
927 992
928 993 /*
929 994 * parse the 'xpv-root' property to create properties used by
930 995 * ufs_mountroot.
931 996 */
932 997 static void
933 998 xen_vbdroot_props(char *s)
934 999 {
935 1000 char vbdpath[VBDPATHLEN] = "/xpvd/xdf@";
936 1001 const char lnamefix[] = "/dev/dsk/c0d";
937 1002 char *pnp;
938 1003 char *prop_p;
939 1004 char mi;
940 1005 short minor;
941 1006 long addr = 0;
942 1007
943 1008 pnp = vbdpath + strlen(vbdpath);
944 1009 prop_p = s + strlen(lnamefix);
945 1010 while ((*prop_p != '\0') && (*prop_p != 's') && (*prop_p != 'p'))
946 1011 addr = addr * 10 + *prop_p++ - '0';
947 1012 (void) snprintf(pnp, VBDPATHLEN, "%lx", addr);
948 1013 pnp = vbdpath + strlen(vbdpath);
949 1014 if (*prop_p == 's')
950 1015 mi = 'a';
951 1016 else if (*prop_p == 'p')
952 1017 mi = 'q';
953 1018 else
954 1019 ASSERT(0); /* shouldn't be here */
955 1020 prop_p++;
956 1021 ASSERT(*prop_p != '\0');
957 1022 if (ISDIGIT(*prop_p)) {
958 1023 minor = *prop_p - '0';
959 1024 prop_p++;
960 1025 if (ISDIGIT(*prop_p)) {
961 1026 minor = minor * 10 + *prop_p - '0';
962 1027 }
963 1028 } else {
964 1029 /* malformed root path, use 0 as default */
965 1030 minor = 0;
966 1031 }
967 1032 ASSERT(minor < 16); /* at most 16 partitions */
968 1033 mi += minor;
969 1034 *pnp++ = ':';
970 1035 *pnp++ = mi;
971 1036 *pnp++ = '\0';
972 1037 bsetprops("fstype", "ufs");
973 1038 bsetprops("bootpath", vbdpath);
974 1039
975 1040 DBG_MSG("VBD bootpath set to ");
976 1041 DBG_MSG(vbdpath);
977 1042 DBG_MSG("\n");
978 1043 }
979 1044
980 1045 /*
981 1046 * parse the xpv-nfsroot property to create properties used by
982 1047 * nfs_mountroot.
983 1048 */
|
↓ open down ↓ |
253 lines elided |
↑ open up ↑ |
984 1049 static void
985 1050 xen_nfsroot_props(char *s)
986 1051 {
987 1052 char *prop_map[] = {
988 1053 BP_SERVER_IP, /* server IP address */
989 1054 BP_SERVER_NAME, /* server hostname */
990 1055 BP_SERVER_PATH, /* root path */
991 1056 };
992 1057 int n_prop = sizeof (prop_map) / sizeof (prop_map[0]);
993 1058
994 - bsetprop("fstype", 6, "nfs", 4);
1059 + bsetprops("fstype", "nfs");
995 1060
996 1061 xen_parse_props(s, prop_map, n_prop);
997 1062
998 1063 /*
999 1064 * If a server name wasn't specified, use a default.
1000 1065 */
1001 1066 if (do_bsys_getproplen(NULL, BP_SERVER_NAME) == -1)
1002 1067 bsetprops(BP_SERVER_NAME, "unknown");
1003 1068 }
1004 1069
1005 1070 /*
1006 1071 * Extract our IP address, etc. from the "xpv-ip" property.
1007 1072 */
1008 1073 static void
1009 1074 xen_ip_props(char *s)
1010 1075 {
1011 1076 char *prop_map[] = {
1012 1077 BP_HOST_IP, /* IP address */
1013 1078 NULL, /* NFS server IP address (ignored in */
1014 1079 /* favour of xpv-nfsroot) */
1015 1080 BP_ROUTER_IP, /* IP gateway */
1016 1081 BP_SUBNET_MASK, /* IP subnet mask */
1017 1082 "xpv-hostname", /* hostname (ignored) */
1018 1083 BP_NETWORK_INTERFACE, /* interface name */
1019 1084 "xpv-hcp", /* host configuration protocol */
1020 1085 };
1021 1086 int n_prop = sizeof (prop_map) / sizeof (prop_map[0]);
1022 1087 char ifname[IFNAMSIZ];
1023 1088
1024 1089 xen_parse_props(s, prop_map, n_prop);
1025 1090
1026 1091 /*
1027 1092 * A Linux dom0 administrator expects all interfaces to be
1028 1093 * called "ethX", which is not the case here.
1029 1094 *
1030 1095 * If the interface name specified is "eth0", presume that
1031 1096 * this is really intended to be "xnf0" (the first domU ->
1032 1097 * dom0 interface for this domain).
1033 1098 */
1034 1099 if ((do_bsys_getprop(NULL, BP_NETWORK_INTERFACE, ifname) == 0) &&
1035 1100 (strcmp("eth0", ifname) == 0)) {
1036 1101 bsetprops(BP_NETWORK_INTERFACE, "xnf0");
1037 1102 bop_printf(NULL,
1038 1103 "network interface name 'eth0' replaced with 'xnf0'\n");
1039 1104 }
1040 1105 }
1041 1106
1042 1107 #else /* __xpv */
1043 1108
1044 1109 static void
1045 1110 setup_rarp_props(struct sol_netinfo *sip)
1046 1111 {
1047 1112 char buf[BUFLEN]; /* to hold ip/mac addrs */
1048 1113 uint8_t *val;
1049 1114
1050 1115 val = (uint8_t *)&sip->sn_ciaddr;
1051 1116 (void) snprintf(buf, BUFLEN, "%d.%d.%d.%d",
1052 1117 val[0], val[1], val[2], val[3]);
1053 1118 bsetprops(BP_HOST_IP, buf);
1054 1119
1055 1120 val = (uint8_t *)&sip->sn_siaddr;
1056 1121 (void) snprintf(buf, BUFLEN, "%d.%d.%d.%d",
1057 1122 val[0], val[1], val[2], val[3]);
1058 1123 bsetprops(BP_SERVER_IP, buf);
1059 1124
1060 1125 if (sip->sn_giaddr != 0) {
1061 1126 val = (uint8_t *)&sip->sn_giaddr;
1062 1127 (void) snprintf(buf, BUFLEN, "%d.%d.%d.%d",
1063 1128 val[0], val[1], val[2], val[3]);
1064 1129 bsetprops(BP_ROUTER_IP, buf);
1065 1130 }
1066 1131
1067 1132 if (sip->sn_netmask != 0) {
1068 1133 val = (uint8_t *)&sip->sn_netmask;
1069 1134 (void) snprintf(buf, BUFLEN, "%d.%d.%d.%d",
1070 1135 val[0], val[1], val[2], val[3]);
1071 1136 bsetprops(BP_SUBNET_MASK, buf);
1072 1137 }
1073 1138
1074 1139 if (sip->sn_mactype != 4 || sip->sn_maclen != 6) {
1075 1140 bop_printf(NULL, "unsupported mac type %d, mac len %d\n",
1076 1141 sip->sn_mactype, sip->sn_maclen);
1077 1142 } else {
1078 1143 val = sip->sn_macaddr;
1079 1144 (void) snprintf(buf, BUFLEN, "%x:%x:%x:%x:%x:%x",
1080 1145 val[0], val[1], val[2], val[3], val[4], val[5]);
1081 1146 bsetprops(BP_BOOT_MAC, buf);
1082 1147 }
1083 1148 }
1084 1149
1085 1150 #endif /* __xpv */
1086 1151
1087 1152 static void
1088 1153 build_panic_cmdline(const char *cmd, int cmdlen)
1089 1154 {
1090 1155 int proplen;
1091 1156 size_t arglen;
1092 1157
1093 1158 arglen = sizeof (fastreboot_onpanic_args);
1094 1159 /*
1095 1160 * If we allready have fastreboot-onpanic set to zero,
1096 1161 * don't add them again.
1097 1162 */
1098 1163 if ((proplen = do_bsys_getproplen(NULL, FASTREBOOT_ONPANIC)) > 0 &&
1099 1164 proplen <= sizeof (fastreboot_onpanic_cmdline)) {
1100 1165 (void) do_bsys_getprop(NULL, FASTREBOOT_ONPANIC,
1101 1166 fastreboot_onpanic_cmdline);
1102 1167 if (FASTREBOOT_ONPANIC_NOTSET(fastreboot_onpanic_cmdline))
1103 1168 arglen = 1;
1104 1169 }
1105 1170
1106 1171 /*
1107 1172 * construct fastreboot_onpanic_cmdline
1108 1173 */
1109 1174 if (cmdlen + arglen > sizeof (fastreboot_onpanic_cmdline)) {
1110 1175 DBG_MSG("Command line too long: clearing "
1111 1176 FASTREBOOT_ONPANIC "\n");
1112 1177 fastreboot_onpanic = 0;
1113 1178 } else {
1114 1179 bcopy(cmd, fastreboot_onpanic_cmdline, cmdlen);
1115 1180 if (arglen != 1)
1116 1181 bcopy(fastreboot_onpanic_args,
1117 1182 fastreboot_onpanic_cmdline + cmdlen, arglen);
1118 1183 else
1119 1184 fastreboot_onpanic_cmdline[cmdlen] = 0;
1120 1185 }
1121 1186 }
1122 1187
1123 1188
1124 1189 #ifndef __xpv
1125 1190 /*
1126 1191 * Construct boot command line for Fast Reboot. The saved_cmdline
1127 1192 * is also reported by "eeprom bootcmd".
1128 1193 */
1129 1194 static void
1130 1195 build_fastboot_cmdline(struct xboot_info *xbp)
1131 1196 {
1132 1197 saved_cmdline_len = strlen(xbp->bi_cmdline) + 1;
1133 1198 if (saved_cmdline_len > FASTBOOT_SAVED_CMDLINE_LEN) {
1134 1199 DBG(saved_cmdline_len);
1135 1200 DBG_MSG("Command line too long: clearing fastreboot_capable\n");
1136 1201 fastreboot_capable = 0;
1137 1202 } else {
1138 1203 bcopy((void *)(xbp->bi_cmdline), (void *)saved_cmdline,
1139 1204 saved_cmdline_len);
1140 1205 saved_cmdline[saved_cmdline_len - 1] = '\0';
1141 1206 build_panic_cmdline(saved_cmdline, saved_cmdline_len - 1);
1142 1207 }
1143 1208 }
1144 1209
1145 1210 /*
1146 1211 * Save memory layout, disk drive information, unix and boot archive sizes for
1147 1212 * Fast Reboot.
1148 1213 */
1149 1214 static void
1150 1215 save_boot_info(struct xboot_info *xbi)
1151 1216 {
1152 1217 multiboot_info_t *mbi = xbi->bi_mb_info;
1153 1218 struct boot_modules *modp;
1154 1219 int i;
1155 1220
1156 1221 bcopy(mbi, &saved_mbi, sizeof (multiboot_info_t));
1157 1222 if (mbi->mmap_length > sizeof (saved_mmap)) {
1158 1223 DBG_MSG("mbi->mmap_length too big: clearing "
1159 1224 "fastreboot_capable\n");
1160 1225 fastreboot_capable = 0;
1161 1226 } else {
1162 1227 bcopy((void *)(uintptr_t)mbi->mmap_addr, (void *)saved_mmap,
1163 1228 mbi->mmap_length);
1164 1229 }
1165 1230
1166 1231 if ((mbi->flags & MB_INFO_DRIVE_INFO) != 0) {
1167 1232 if (mbi->drives_length > sizeof (saved_drives)) {
1168 1233 DBG(mbi->drives_length);
1169 1234 DBG_MSG("mbi->drives_length too big: clearing "
1170 1235 "fastreboot_capable\n");
1171 1236 fastreboot_capable = 0;
1172 1237 } else {
1173 1238 bcopy((void *)(uintptr_t)mbi->drives_addr,
1174 1239 (void *)saved_drives, mbi->drives_length);
1175 1240 }
1176 1241 } else {
1177 1242 saved_mbi.drives_length = 0;
1178 1243 saved_mbi.drives_addr = NULL;
1179 1244 }
1180 1245
1181 1246 /*
1182 1247 * Current file sizes. Used by fastboot.c to figure out how much
1183 1248 * memory to reserve for panic reboot.
1184 1249 * Use the module list from the dboot-constructed xboot_info
1185 1250 * instead of the list referenced by the multiboot structure
1186 1251 * because that structure may not be addressable now.
1187 1252 */
1188 1253 saved_file_size[FASTBOOT_NAME_UNIX] = FOUR_MEG - PAGESIZE;
1189 1254 for (i = 0, modp = (struct boot_modules *)(uintptr_t)xbi->bi_modules;
1190 1255 i < xbi->bi_module_cnt; i++, modp++) {
1191 1256 saved_file_size[FASTBOOT_NAME_BOOTARCHIVE] += modp->bm_size;
1192 1257 }
1193 1258 }
1194 1259 #endif /* __xpv */
1195 1260
1196 1261 /*
1197 1262 * Import boot environment module variables as properties, applying
1198 1263 * blacklist filter for variables we know we will not use.
1199 1264 *
1200 1265 * Since the environment can be relatively large, containing many variables
1201 1266 * used only for boot loader purposes, we will use a blacklist based filter.
1202 1267 * To keep the blacklist from growing too large, we use prefix based filtering.
1203 1268 * This is possible because in many cases, the loader variable names are
1204 1269 * using a structured layout.
1205 1270 *
1206 1271 * We will not overwrite already set properties.
1207 1272 */
1208 1273 static struct bop_blacklist {
1209 1274 const char *bl_name;
1210 1275 int bl_name_len;
1211 1276 } bop_prop_blacklist[] = {
1212 1277 { "ISADIR", sizeof ("ISADIR") },
1213 1278 { "acpi", sizeof ("acpi") },
1214 1279 { "autoboot_delay", sizeof ("autoboot_delay") },
1215 1280 { "autoboot_delay", sizeof ("autoboot_delay") },
1216 1281 { "beansi_", sizeof ("beansi_") },
1217 1282 { "beastie", sizeof ("beastie") },
1218 1283 { "bemenu", sizeof ("bemenu") },
1219 1284 { "boot.", sizeof ("boot.") },
1220 1285 { "bootenv", sizeof ("bootenv") },
1221 1286 { "currdev", sizeof ("currdev") },
1222 1287 { "dhcp.", sizeof ("dhcp.") },
1223 1288 { "interpret", sizeof ("interpret") },
1224 1289 { "kernel", sizeof ("kernel") },
1225 1290 { "loaddev", sizeof ("loaddev") },
1226 1291 { "loader_", sizeof ("loader_") },
1227 1292 { "module_path", sizeof ("module_path") },
1228 1293 { "nfs.", sizeof ("nfs.") },
1229 1294 { "pcibios", sizeof ("pcibios") },
1230 1295 { "prompt", sizeof ("prompt") },
1231 1296 { "smbios", sizeof ("smbios") },
1232 1297 { "tem", sizeof ("tem") },
1233 1298 { "twiddle_divisor", sizeof ("twiddle_divisor") },
1234 1299 { "zfs_be", sizeof ("zfs_be") },
1235 1300 };
1236 1301
1237 1302 /*
1238 1303 * Match the name against prefixes in above blacklist. If the match was
1239 1304 * found, this name is blacklisted.
1240 1305 */
1241 1306 static boolean_t
1242 1307 name_is_blacklisted(const char *name)
1243 1308 {
1244 1309 int i, n;
1245 1310
1246 1311 n = sizeof (bop_prop_blacklist) / sizeof (bop_prop_blacklist[0]);
1247 1312 for (i = 0; i < n; i++) {
1248 1313 if (strncmp(bop_prop_blacklist[i].bl_name, name,
1249 1314 bop_prop_blacklist[i].bl_name_len - 1) == 0) {
1250 1315 return (B_TRUE);
1251 1316 }
1252 1317 }
1253 1318 return (B_FALSE);
1254 1319 }
1255 1320
1256 1321 static void
1257 1322 process_boot_environment(struct boot_modules *benv)
1258 1323 {
1259 1324 char *env, *ptr, *name, *value;
1260 1325 uint32_t size, name_len, value_len;
1261 1326
1262 1327 if (benv == NULL || benv->bm_type != BMT_ENV)
1263 1328 return;
1264 1329 ptr = env = benv->bm_addr;
1265 1330 size = benv->bm_size;
1266 1331 do {
1267 1332 name = ptr;
1268 1333 /* find '=' */
1269 1334 while (*ptr != '=') {
1270 1335 ptr++;
1271 1336 if (ptr > env + size) /* Something is very wrong. */
1272 1337 return;
1273 1338 }
1274 1339 name_len = ptr - name;
1275 1340 if (sizeof (buffer) <= name_len)
1276 1341 continue;
1277 1342
1278 1343 (void) strncpy(buffer, name, sizeof (buffer));
1279 1344 buffer[name_len] = '\0';
1280 1345 name = buffer;
1281 1346
1282 1347 value_len = 0;
1283 1348 value = ++ptr;
1284 1349 while ((uintptr_t)ptr - (uintptr_t)env < size) {
1285 1350 if (*ptr == '\0') {
1286 1351 ptr++;
1287 1352 value_len = (uintptr_t)ptr - (uintptr_t)env;
1288 1353 break;
1289 1354 }
1290 1355 ptr++;
1291 1356 }
1292 1357
1293 1358 /* Did we reach the end of the module? */
1294 1359 if (value_len == 0)
1295 1360 return;
1296 1361
1297 1362 if (*value == '\0')
1298 1363 continue;
1299 1364
1300 1365 /* Is this property already set? */
1301 1366 if (do_bsys_getproplen(NULL, name) >= 0)
1302 1367 continue;
1303 1368
1304 1369 if (name_is_blacklisted(name) == B_TRUE)
1305 1370 continue;
1306 1371
1307 1372 /* Create new property. */
1308 1373 bsetprops(name, value);
1309 1374
1310 1375 /* Avoid reading past the module end. */
1311 1376 if (size <= (uintptr_t)ptr - (uintptr_t)env)
1312 1377 return;
1313 1378 } while (*ptr != '\0');
1314 1379 }
1315 1380
1316 1381 /*
1317 1382 * 1st pass at building the table of boot properties. This includes:
1318 1383 * - values set on the command line: -B a=x,b=y,c=z ....
1319 1384 * - known values we just compute (ie. from xbp)
1320 1385 * - values from /boot/solaris/bootenv.rc (ie. eeprom(1m) values)
1321 1386 *
1322 1387 * the grub command line looked like:
1323 1388 * kernel boot-file [-B prop=value[,prop=value]...] [boot-args]
1324 1389 *
1325 1390 * whoami is the same as boot-file
1326 1391 */
1327 1392 static void
1328 1393 build_boot_properties(struct xboot_info *xbp)
1329 1394 {
1330 1395 char *name;
1331 1396 int name_len;
1332 1397 char *value;
1333 1398 int value_len;
1334 1399 struct boot_modules *bm, *rdbm, *benv = NULL;
1335 1400 char *propbuf;
1336 1401 int quoted = 0;
1337 1402 int boot_arg_len;
1338 1403 uint_t i, midx;
1339 1404 char modid[32];
1340 1405 #ifndef __xpv
1341 1406 static int stdout_val = 0;
1342 1407 uchar_t boot_device;
1343 1408 char str[3];
1344 1409 #endif
1345 1410
1346 1411 /*
1347 1412 * These have to be done first, so that kobj_mount_root() works
1348 1413 */
1349 1414 DBG_MSG("Building boot properties\n");
|
↓ open down ↓ |
345 lines elided |
↑ open up ↑ |
1350 1415 propbuf = do_bsys_alloc(NULL, NULL, MMU_PAGESIZE, 0);
1351 1416 DBG((uintptr_t)propbuf);
1352 1417 if (xbp->bi_module_cnt > 0) {
1353 1418 bm = xbp->bi_modules;
1354 1419 rdbm = NULL;
1355 1420 for (midx = i = 0; i < xbp->bi_module_cnt; i++) {
1356 1421 if (bm[i].bm_type == BMT_ROOTFS) {
1357 1422 rdbm = &bm[i];
1358 1423 continue;
1359 1424 }
1360 - if (bm[i].bm_type == BMT_HASH || bm[i].bm_name == NULL)
1425 + if (bm[i].bm_type == BMT_HASH ||
1426 + bm[i].bm_type == BMT_FONT ||
1427 + bm[i].bm_name == NULL)
1361 1428 continue;
1362 1429
1363 1430 if (bm[i].bm_type == BMT_ENV) {
1364 1431 if (benv == NULL)
1365 1432 benv = &bm[i];
1366 1433 else
1367 1434 continue;
1368 1435 }
1369 1436
1370 1437 (void) snprintf(modid, sizeof (modid),
1371 1438 "module-name-%u", midx);
1372 1439 bsetprops(modid, (char *)bm[i].bm_name);
1373 1440 (void) snprintf(modid, sizeof (modid),
1374 1441 "module-addr-%u", midx);
1375 1442 bsetprop64(modid, (uint64_t)(uintptr_t)bm[i].bm_addr);
1376 1443 (void) snprintf(modid, sizeof (modid),
1377 1444 "module-size-%u", midx);
1378 1445 bsetprop64(modid, (uint64_t)bm[i].bm_size);
1379 1446 ++midx;
1380 1447 }
1381 1448 if (rdbm != NULL) {
1382 1449 bsetprop64("ramdisk_start",
1383 1450 (uint64_t)(uintptr_t)rdbm->bm_addr);
1384 1451 bsetprop64("ramdisk_end",
1385 1452 (uint64_t)(uintptr_t)rdbm->bm_addr + rdbm->bm_size);
1386 1453 }
1387 1454 }
1388 1455
1389 1456 /*
1390 1457 * If there are any boot time modules or hashes present, then disable
1391 1458 * fast reboot.
1392 1459 */
1393 1460 if (xbp->bi_module_cnt > 1) {
1394 1461 fastreboot_disable(FBNS_BOOTMOD);
1395 1462 }
1396 1463
1397 1464 #ifndef __xpv
1398 1465 /*
1399 1466 * Disable fast reboot if we're using the Multiboot 2 boot protocol,
1400 1467 * since we don't currently support MB2 info and module relocation.
1401 1468 * Note that fast reboot will have already been disabled if multiple
1402 1469 * modules are present, since the current implementation assumes that
1403 1470 * we only have a single module, the boot_archive.
1404 1471 */
1405 1472 if (xbp->bi_mb_version != 1) {
1406 1473 fastreboot_disable(FBNS_MULTIBOOT2);
1407 1474 }
1408 1475 #endif
1409 1476
1410 1477 DBG_MSG("Parsing command line for boot properties\n");
1411 1478 value = xbp->bi_cmdline;
1412 1479
1413 1480 /*
1414 1481 * allocate memory to collect boot_args into
1415 1482 */
1416 1483 boot_arg_len = strlen(xbp->bi_cmdline) + 1;
1417 1484 boot_args = do_bsys_alloc(NULL, NULL, boot_arg_len, MMU_PAGESIZE);
1418 1485 boot_args[0] = 0;
1419 1486 boot_arg_len = 0;
1420 1487
1421 1488 #ifdef __xpv
1422 1489 /*
1423 1490 * Xen puts a lot of device information in front of the kernel name
1424 1491 * let's grab them and make them boot properties. The first
1425 1492 * string w/o an "=" in it will be the boot-file property.
1426 1493 */
1427 1494 (void) strcpy(namebuf, "xpv-");
1428 1495 for (;;) {
1429 1496 /*
1430 1497 * get to next property
1431 1498 */
1432 1499 while (ISSPACE(*value))
1433 1500 ++value;
1434 1501 name = value;
1435 1502 /*
1436 1503 * look for an "="
1437 1504 */
1438 1505 while (*value && !ISSPACE(*value) && *value != '=') {
1439 1506 value++;
1440 1507 }
1441 1508 if (*value != '=') { /* no "=" in the property */
1442 1509 value = name;
1443 1510 break;
1444 1511 }
1445 1512 name_len = value - name;
1446 1513 value_len = 0;
1447 1514 /*
1448 1515 * skip over the "="
1449 1516 */
1450 1517 value++;
1451 1518 while (value[value_len] && !ISSPACE(value[value_len])) {
1452 1519 ++value_len;
1453 1520 }
1454 1521 /*
1455 1522 * build property name with "xpv-" prefix
1456 1523 */
1457 1524 if (name_len + 4 > 32) { /* skip if name too long */
1458 1525 value += value_len;
1459 1526 continue;
1460 1527 }
1461 1528 bcopy(name, &namebuf[4], name_len);
1462 1529 name_len += 4;
1463 1530 namebuf[name_len] = 0;
1464 1531 bcopy(value, propbuf, value_len);
1465 1532 propbuf[value_len] = 0;
1466 1533 bsetprops(namebuf, propbuf);
1467 1534
1468 1535 /*
1469 1536 * xpv-root is set to the logical disk name of the xen
1470 1537 * VBD when booting from a disk-based filesystem.
1471 1538 */
1472 1539 if (strcmp(namebuf, "xpv-root") == 0)
1473 1540 xen_vbdroot_props(propbuf);
1474 1541 /*
1475 1542 * While we're here, if we have a "xpv-nfsroot" property
1476 1543 * then we need to set "fstype" to "nfs" so we mount
1477 1544 * our root from the nfs server. Also parse the xpv-nfsroot
1478 1545 * property to create the properties that nfs_mountroot will
1479 1546 * need to find the root and mount it.
1480 1547 */
1481 1548 if (strcmp(namebuf, "xpv-nfsroot") == 0)
1482 1549 xen_nfsroot_props(propbuf);
1483 1550
1484 1551 if (strcmp(namebuf, "xpv-ip") == 0)
1485 1552 xen_ip_props(propbuf);
1486 1553 value += value_len;
1487 1554 }
1488 1555 #endif
1489 1556
1490 1557 while (ISSPACE(*value))
1491 1558 ++value;
1492 1559 /*
1493 1560 * value now points at the boot-file
1494 1561 */
1495 1562 value_len = 0;
1496 1563 while (value[value_len] && !ISSPACE(value[value_len]))
1497 1564 ++value_len;
1498 1565 if (value_len > 0) {
1499 1566 whoami = propbuf;
1500 1567 bcopy(value, whoami, value_len);
1501 1568 whoami[value_len] = 0;
1502 1569 bsetprops("boot-file", whoami);
1503 1570 /*
1504 1571 * strip leading path stuff from whoami, so running from
1505 1572 * PXE/miniroot makes sense.
1506 1573 */
1507 1574 if (strstr(whoami, "/platform/") != NULL)
1508 1575 whoami = strstr(whoami, "/platform/");
1509 1576 bsetprops("whoami", whoami);
1510 1577 }
1511 1578
1512 1579 /*
1513 1580 * Values forcibly set boot properties on the command line via -B.
1514 1581 * Allow use of quotes in values. Other stuff goes on kernel
1515 1582 * command line.
1516 1583 */
1517 1584 name = value + value_len;
1518 1585 while (*name != 0) {
1519 1586 /*
1520 1587 * anything not " -B" is copied to the command line
1521 1588 */
1522 1589 if (!ISSPACE(name[0]) || name[1] != '-' || name[2] != 'B') {
1523 1590 boot_args[boot_arg_len++] = *name;
1524 1591 boot_args[boot_arg_len] = 0;
1525 1592 ++name;
1526 1593 continue;
1527 1594 }
1528 1595
1529 1596 /*
1530 1597 * skip the " -B" and following white space
1531 1598 */
1532 1599 name += 3;
1533 1600 while (ISSPACE(*name))
1534 1601 ++name;
1535 1602 while (*name && !ISSPACE(*name)) {
1536 1603 value = strstr(name, "=");
1537 1604 if (value == NULL)
1538 1605 break;
1539 1606 name_len = value - name;
1540 1607 ++value;
1541 1608 value_len = 0;
1542 1609 quoted = 0;
1543 1610 for (; ; ++value_len) {
1544 1611 if (!value[value_len])
1545 1612 break;
1546 1613
1547 1614 /*
1548 1615 * is this value quoted?
1549 1616 */
1550 1617 if (value_len == 0 &&
1551 1618 (value[0] == '\'' || value[0] == '"')) {
1552 1619 quoted = value[0];
1553 1620 ++value_len;
1554 1621 }
1555 1622
1556 1623 /*
1557 1624 * In the quote accept any character,
1558 1625 * but look for ending quote.
1559 1626 */
1560 1627 if (quoted) {
1561 1628 if (value[value_len] == quoted)
1562 1629 quoted = 0;
1563 1630 continue;
1564 1631 }
|
↓ open down ↓ |
194 lines elided |
↑ open up ↑ |
1565 1632
1566 1633 /*
1567 1634 * a comma or white space ends the value
1568 1635 */
1569 1636 if (value[value_len] == ',' ||
1570 1637 ISSPACE(value[value_len]))
1571 1638 break;
1572 1639 }
1573 1640
1574 1641 if (value_len == 0) {
1575 - bsetprop(name, name_len, "true", 5);
1642 + bsetprop(DDI_PROP_TYPE_ANY, name, name_len,
1643 + NULL, 0);
1576 1644 } else {
1577 1645 char *v = value;
1578 1646 int l = value_len;
1579 1647 if (v[0] == v[l - 1] &&
1580 1648 (v[0] == '\'' || v[0] == '"')) {
1581 1649 ++v;
1582 1650 l -= 2;
1583 1651 }
1584 1652 bcopy(v, propbuf, l);
1585 1653 propbuf[l] = '\0';
1586 - bsetprop(name, name_len, propbuf,
1587 - l + 1);
1654 + bsetprop(DDI_PROP_TYPE_STRING, name, name_len,
1655 + propbuf, l + 1);
1588 1656 }
1589 1657 name = value + value_len;
1590 1658 while (*name == ',')
1591 1659 ++name;
1592 1660 }
1593 1661 }
1594 1662
1595 1663 /*
1596 1664 * set boot-args property
1597 1665 * 1275 name is bootargs, so set
1598 1666 * that too
1599 1667 */
1600 1668 bsetprops("boot-args", boot_args);
1601 1669 bsetprops("bootargs", boot_args);
1602 1670
1603 1671 process_boot_environment(benv);
1604 1672
1605 1673 #ifndef __xpv
1606 1674 /*
1607 1675 * Build boot command line for Fast Reboot
1608 1676 */
1609 1677 build_fastboot_cmdline(xbp);
1610 1678
1611 1679 if (xbp->bi_mb_version == 1) {
1612 1680 multiboot_info_t *mbi = xbp->bi_mb_info;
1613 1681 int netboot;
1614 1682 struct sol_netinfo *sip;
1615 1683
1616 1684 /*
1617 1685 * set the BIOS boot device from GRUB
1618 1686 */
1619 1687 netboot = 0;
1620 1688
1621 1689 /*
1622 1690 * Save various boot information for Fast Reboot
1623 1691 */
1624 1692 save_boot_info(xbp);
1625 1693
1626 1694 if (mbi != NULL && mbi->flags & MB_INFO_BOOTDEV) {
1627 1695 boot_device = mbi->boot_device >> 24;
1628 1696 if (boot_device == 0x20)
1629 1697 netboot++;
1630 1698 str[0] = (boot_device >> 4) + '0';
1631 1699 str[1] = (boot_device & 0xf) + '0';
1632 1700 str[2] = 0;
1633 1701 bsetprops("bios-boot-device", str);
1634 1702 } else {
1635 1703 netboot = 1;
|
↓ open down ↓ |
38 lines elided |
↑ open up ↑ |
1636 1704 }
1637 1705
1638 1706 /*
1639 1707 * In the netboot case, drives_info is overloaded with the
1640 1708 * dhcp ack. This is not multiboot compliant and requires
1641 1709 * special pxegrub!
1642 1710 */
1643 1711 if (netboot && mbi->drives_length != 0) {
1644 1712 sip = (struct sol_netinfo *)(uintptr_t)mbi->drives_addr;
1645 1713 if (sip->sn_infotype == SN_TYPE_BOOTP)
1646 - bsetprop("bootp-response",
1714 + bsetprop(DDI_PROP_TYPE_BYTE,
1715 + "bootp-response",
1647 1716 sizeof ("bootp-response"),
1648 1717 (void *)(uintptr_t)mbi->drives_addr,
1649 1718 mbi->drives_length);
1650 1719 else if (sip->sn_infotype == SN_TYPE_RARP)
1651 1720 setup_rarp_props(sip);
1652 1721 }
1653 1722 } else {
1654 1723 multiboot2_info_header_t *mbi = xbp->bi_mb_info;
1655 1724 multiboot_tag_bootdev_t *bootdev = NULL;
1656 1725 multiboot_tag_network_t *netdev = NULL;
1657 1726
1658 1727 if (mbi != NULL) {
1659 1728 bootdev = dboot_multiboot2_find_tag(mbi,
1660 1729 MULTIBOOT_TAG_TYPE_BOOTDEV);
1661 1730 netdev = dboot_multiboot2_find_tag(mbi,
1662 1731 MULTIBOOT_TAG_TYPE_NETWORK);
|
↓ open down ↓ |
6 lines elided |
↑ open up ↑ |
1663 1732 }
1664 1733 if (bootdev != NULL) {
1665 1734 DBG(bootdev->mb_biosdev);
1666 1735 boot_device = bootdev->mb_biosdev;
1667 1736 str[0] = (boot_device >> 4) + '0';
1668 1737 str[1] = (boot_device & 0xf) + '0';
1669 1738 str[2] = 0;
1670 1739 bsetprops("bios-boot-device", str);
1671 1740 }
1672 1741 if (netdev != NULL) {
1673 - bsetprop("bootp-response", sizeof ("bootp-response"),
1742 + bsetprop(DDI_PROP_TYPE_BYTE,
1743 + "bootp-response", sizeof ("bootp-response"),
1674 1744 (void *)(uintptr_t)netdev->mb_dhcpack,
1675 1745 netdev->mb_size -
1676 1746 sizeof (multiboot_tag_network_t));
1677 1747 }
1678 1748 }
1679 1749
1680 - bsetprop("stdout", strlen("stdout"),
1681 - &stdout_val, sizeof (stdout_val));
1750 + bsetprop32("stdout", stdout_val);
1682 1751 #endif /* __xpv */
1683 1752
1684 1753 /*
1685 1754 * more conjured up values for made up things....
1686 1755 */
1687 1756 #if defined(__xpv)
1688 1757 bsetprops("mfg-name", "i86xpv");
1689 1758 bsetprops("impl-arch-name", "i86xpv");
1690 1759 #else
1691 1760 bsetprops("mfg-name", "i86pc");
1692 1761 bsetprops("impl-arch-name", "i86pc");
1693 1762 #endif
1694 1763
1695 1764 /*
1696 1765 * Build firmware-provided system properties
1697 1766 */
1698 1767 build_firmware_properties(xbp);
1699 1768
1700 1769 /*
1701 1770 * XXPV
1702 1771 *
1703 1772 * Find out what these are:
1704 1773 * - cpuid_feature_ecx_include
1705 1774 * - cpuid_feature_ecx_exclude
1706 1775 * - cpuid_feature_edx_include
1707 1776 * - cpuid_feature_edx_exclude
1708 1777 *
1709 1778 * Find out what these are in multiboot:
1710 1779 * - netdev-path
1711 1780 * - fstype
1712 1781 */
1713 1782 }
1714 1783
1715 1784 #ifdef __xpv
1716 1785 /*
1717 1786 * Under the Hypervisor, memory usable for DMA may be scarce. One
1718 1787 * very likely large pool of DMA friendly memory is occupied by
1719 1788 * the boot_archive, as it was loaded by grub into low MFNs.
1720 1789 *
1721 1790 * Here we free up that memory by copying the boot archive to what are
1722 1791 * likely higher MFN pages and then swapping the mfn/pfn mappings.
1723 1792 */
1724 1793 #define PFN_2GIG 0x80000
1725 1794 static void
1726 1795 relocate_boot_archive(struct xboot_info *xbp)
1727 1796 {
1728 1797 mfn_t max_mfn = HYPERVISOR_memory_op(XENMEM_maximum_ram_page, NULL);
1729 1798 struct boot_modules *bm = xbp->bi_modules;
1730 1799 uintptr_t va;
1731 1800 pfn_t va_pfn;
1732 1801 mfn_t va_mfn;
1733 1802 caddr_t copy;
1734 1803 pfn_t copy_pfn;
1735 1804 mfn_t copy_mfn;
1736 1805 size_t len;
1737 1806 int slop;
1738 1807 int total = 0;
1739 1808 int relocated = 0;
1740 1809 int mmu_update_return;
1741 1810 mmu_update_t t[2];
1742 1811 x86pte_t pte;
1743 1812
1744 1813 /*
1745 1814 * If all MFN's are below 2Gig, don't bother doing this.
1746 1815 */
1747 1816 if (max_mfn < PFN_2GIG)
1748 1817 return;
1749 1818 if (xbp->bi_module_cnt < 1) {
1750 1819 DBG_MSG("no boot_archive!");
1751 1820 return;
1752 1821 }
1753 1822
1754 1823 DBG_MSG("moving boot_archive to high MFN memory\n");
1755 1824 va = (uintptr_t)bm->bm_addr;
1756 1825 len = bm->bm_size;
1757 1826 slop = va & MMU_PAGEOFFSET;
1758 1827 if (slop) {
1759 1828 va += MMU_PAGESIZE - slop;
1760 1829 len -= MMU_PAGESIZE - slop;
1761 1830 }
1762 1831 len = P2ALIGN(len, MMU_PAGESIZE);
1763 1832
1764 1833 /*
1765 1834 * Go through all boot_archive pages, swapping any low MFN pages
1766 1835 * with memory at next_phys.
1767 1836 */
1768 1837 while (len != 0) {
1769 1838 ++total;
1770 1839 va_pfn = mmu_btop(va - ONE_GIG);
1771 1840 va_mfn = mfn_list[va_pfn];
1772 1841 if (mfn_list[va_pfn] < PFN_2GIG) {
1773 1842 copy = kbm_remap_window(next_phys, 1);
1774 1843 bcopy((void *)va, copy, MMU_PAGESIZE);
1775 1844 copy_pfn = mmu_btop(next_phys);
1776 1845 copy_mfn = mfn_list[copy_pfn];
1777 1846
1778 1847 pte = mfn_to_ma(copy_mfn) | PT_NOCONSIST | PT_VALID;
1779 1848 if (HYPERVISOR_update_va_mapping(va, pte,
1780 1849 UVMF_INVLPG | UVMF_LOCAL))
1781 1850 bop_panic("relocate_boot_archive(): "
1782 1851 "HYPERVISOR_update_va_mapping() failed");
1783 1852
1784 1853 mfn_list[va_pfn] = copy_mfn;
1785 1854 mfn_list[copy_pfn] = va_mfn;
1786 1855
1787 1856 t[0].ptr = mfn_to_ma(copy_mfn) | MMU_MACHPHYS_UPDATE;
1788 1857 t[0].val = va_pfn;
1789 1858 t[1].ptr = mfn_to_ma(va_mfn) | MMU_MACHPHYS_UPDATE;
1790 1859 t[1].val = copy_pfn;
1791 1860 if (HYPERVISOR_mmu_update(t, 2, &mmu_update_return,
1792 1861 DOMID_SELF) != 0 || mmu_update_return != 2)
1793 1862 bop_panic("relocate_boot_archive(): "
1794 1863 "HYPERVISOR_mmu_update() failed");
1795 1864
1796 1865 next_phys += MMU_PAGESIZE;
1797 1866 ++relocated;
1798 1867 }
1799 1868 len -= MMU_PAGESIZE;
1800 1869 va += MMU_PAGESIZE;
1801 1870 }
1802 1871 DBG_MSG("Relocated pages:\n");
1803 1872 DBG(relocated);
1804 1873 DBG_MSG("Out of total pages:\n");
1805 1874 DBG(total);
1806 1875 }
1807 1876 #endif /* __xpv */
1808 1877
1809 1878 #if !defined(__xpv)
1810 1879 /*
1811 1880 * simple description of a stack frame (args are 32 bit only currently)
1812 1881 */
1813 1882 typedef struct bop_frame {
1814 1883 struct bop_frame *old_frame;
1815 1884 pc_t retaddr;
1816 1885 long arg[1];
1817 1886 } bop_frame_t;
1818 1887
1819 1888 void
1820 1889 bop_traceback(bop_frame_t *frame)
1821 1890 {
1822 1891 pc_t pc;
1823 1892 int cnt;
1824 1893 char *ksym;
1825 1894 ulong_t off;
1826 1895
1827 1896 bop_printf(NULL, "Stack traceback:\n");
1828 1897 for (cnt = 0; cnt < 30; ++cnt) { /* up to 30 frames */
1829 1898 pc = frame->retaddr;
1830 1899 if (pc == 0)
1831 1900 break;
1832 1901 ksym = kobj_getsymname(pc, &off);
1833 1902 if (ksym)
1834 1903 bop_printf(NULL, " %s+%lx", ksym, off);
1835 1904 else
1836 1905 bop_printf(NULL, " 0x%lx", pc);
1837 1906
1838 1907 frame = frame->old_frame;
1839 1908 if (frame == 0) {
1840 1909 bop_printf(NULL, "\n");
1841 1910 break;
1842 1911 }
1843 1912 bop_printf(NULL, "\n");
1844 1913 }
1845 1914 }
1846 1915
1847 1916 struct trapframe {
1848 1917 ulong_t error_code; /* optional */
1849 1918 ulong_t inst_ptr;
1850 1919 ulong_t code_seg;
1851 1920 ulong_t flags_reg;
1852 1921 ulong_t stk_ptr;
1853 1922 ulong_t stk_seg;
1854 1923 };
1855 1924
1856 1925 void
1857 1926 bop_trap(ulong_t *tfp)
1858 1927 {
1859 1928 struct trapframe *tf = (struct trapframe *)tfp;
1860 1929 bop_frame_t fakeframe;
1861 1930 static int depth = 0;
1862 1931
1863 1932 /*
1864 1933 * Check for an infinite loop of traps.
1865 1934 */
1866 1935 if (++depth > 2)
1867 1936 bop_panic("Nested trap");
1868 1937
1869 1938 bop_printf(NULL, "Unexpected trap\n");
1870 1939
1871 1940 /*
1872 1941 * adjust the tf for optional error_code by detecting the code selector
1873 1942 */
1874 1943 if (tf->code_seg != B64CODE_SEL)
1875 1944 tf = (struct trapframe *)(tfp - 1);
1876 1945 else
1877 1946 bop_printf(NULL, "error code 0x%lx\n",
1878 1947 tf->error_code & 0xffffffff);
1879 1948
1880 1949 bop_printf(NULL, "instruction pointer 0x%lx\n", tf->inst_ptr);
1881 1950 bop_printf(NULL, "code segment 0x%lx\n", tf->code_seg & 0xffff);
1882 1951 bop_printf(NULL, "flags register 0x%lx\n", tf->flags_reg);
1883 1952 bop_printf(NULL, "return %%rsp 0x%lx\n", tf->stk_ptr);
1884 1953 bop_printf(NULL, "return %%ss 0x%lx\n", tf->stk_seg & 0xffff);
1885 1954
1886 1955 /* grab %[er]bp pushed by our code from the stack */
1887 1956 fakeframe.old_frame = (bop_frame_t *)*(tfp - 3);
1888 1957 fakeframe.retaddr = (pc_t)tf->inst_ptr;
1889 1958 bop_printf(NULL, "Attempting stack backtrace:\n");
1890 1959 bop_traceback(&fakeframe);
1891 1960 bop_panic("unexpected trap in early boot");
1892 1961 }
1893 1962
1894 1963 extern void bop_trap_handler(void);
1895 1964
1896 1965 static gate_desc_t *bop_idt;
1897 1966
1898 1967 static desctbr_t bop_idt_info;
1899 1968
1900 1969 /*
1901 1970 * Install a temporary IDT that lets us catch errors in the boot time code.
1902 1971 * We shouldn't get any faults at all while this is installed, so we'll
1903 1972 * just generate a traceback and exit.
1904 1973 */
1905 1974 static void
1906 1975 bop_idt_init(void)
1907 1976 {
1908 1977 int t;
1909 1978
1910 1979 bop_idt = (gate_desc_t *)
1911 1980 do_bsys_alloc(NULL, NULL, MMU_PAGESIZE, MMU_PAGESIZE);
1912 1981 bzero(bop_idt, MMU_PAGESIZE);
1913 1982 for (t = 0; t < NIDT; ++t) {
1914 1983 /*
1915 1984 * Note that since boot runs without a TSS, the
1916 1985 * double fault handler cannot use an alternate stack (64-bit).
1917 1986 */
1918 1987 set_gatesegd(&bop_idt[t], &bop_trap_handler, B64CODE_SEL,
1919 1988 SDT_SYSIGT, TRP_KPL, 0);
1920 1989 }
1921 1990 bop_idt_info.dtr_limit = (NIDT * sizeof (gate_desc_t)) - 1;
1922 1991 bop_idt_info.dtr_base = (uintptr_t)bop_idt;
1923 1992 wr_idtr(&bop_idt_info);
1924 1993 }
1925 1994 #endif /* !defined(__xpv) */
1926 1995
1927 1996 /*
1928 1997 * This is where we enter the kernel. It dummies up the boot_ops and
1929 1998 * boot_syscalls vectors and jumps off to _kobj_boot()
1930 1999 */
1931 2000 void
1932 2001 _start(struct xboot_info *xbp)
1933 2002 {
1934 2003 bootops_t *bops = &bootop;
1935 2004 extern void _kobj_boot();
1936 2005
1937 2006 /*
1938 2007 * 1st off - initialize the console for any error messages
1939 2008 */
1940 2009 xbootp = xbp;
1941 2010 #ifdef __xpv
1942 2011 HYPERVISOR_shared_info = (void *)xbp->bi_shared_info;
1943 2012 xen_info = xbp->bi_xen_start_info;
1944 2013 #endif
1945 2014
1946 2015 #ifndef __xpv
1947 2016 if (*((uint32_t *)(FASTBOOT_SWTCH_PA + FASTBOOT_STACK_OFFSET)) ==
1948 2017 FASTBOOT_MAGIC) {
1949 2018 post_fastreboot = 1;
1950 2019 *((uint32_t *)(FASTBOOT_SWTCH_PA + FASTBOOT_STACK_OFFSET)) = 0;
1951 2020 }
1952 2021 #endif
1953 2022
1954 2023 bcons_init(xbp);
1955 2024 have_console = 1;
1956 2025
1957 2026 /*
1958 2027 * enable debugging
1959 2028 */
1960 2029 if (find_boot_prop("kbm_debug") != NULL)
1961 2030 kbm_debug = 1;
1962 2031
1963 2032 DBG_MSG("\n\n*** Entered Solaris in _start() cmdline is: ");
1964 2033 DBG_MSG((char *)xbp->bi_cmdline);
1965 2034 DBG_MSG("\n\n\n");
1966 2035
1967 2036 /*
1968 2037 * physavail is no longer used by startup
1969 2038 */
1970 2039 bm.physinstalled = xbp->bi_phys_install;
1971 2040 bm.pcimem = xbp->bi_pcimem;
1972 2041 bm.rsvdmem = xbp->bi_rsvdmem;
1973 2042 bm.physavail = NULL;
1974 2043
1975 2044 /*
1976 2045 * initialize the boot time allocator
1977 2046 */
1978 2047 next_phys = xbp->bi_next_paddr;
1979 2048 DBG(next_phys);
1980 2049 next_virt = (uintptr_t)xbp->bi_next_vaddr;
1981 2050 DBG(next_virt);
1982 2051 DBG_MSG("Initializing boot time memory management...");
1983 2052 #ifdef __xpv
1984 2053 {
1985 2054 xen_platform_parameters_t p;
1986 2055
1987 2056 /* This call shouldn't fail, dboot already did it once. */
1988 2057 (void) HYPERVISOR_xen_version(XENVER_platform_parameters, &p);
1989 2058 mfn_to_pfn_mapping = (pfn_t *)(xen_virt_start = p.virt_start);
1990 2059 DBG(xen_virt_start);
1991 2060 }
1992 2061 #endif
1993 2062 kbm_init(xbp);
1994 2063 DBG_MSG("done\n");
1995 2064
1996 2065 /*
1997 2066 * Fill in the bootops vector
1998 2067 */
1999 2068 bops->bsys_version = BO_VERSION;
2000 2069 bops->boot_mem = &bm;
2001 2070 bops->bsys_alloc = do_bsys_alloc;
2002 2071 bops->bsys_free = do_bsys_free;
2003 2072 bops->bsys_getproplen = do_bsys_getproplen;
2004 2073 bops->bsys_getprop = do_bsys_getprop;
2005 2074 bops->bsys_nextprop = do_bsys_nextprop;
2006 2075 bops->bsys_printf = bop_printf;
2007 2076 bops->bsys_doint = do_bsys_doint;
2008 2077
2009 2078 /*
2010 2079 * BOP_EALLOC() is no longer needed
2011 2080 */
2012 2081 bops->bsys_ealloc = do_bsys_ealloc;
2013 2082
2014 2083 #ifdef __xpv
2015 2084 /*
2016 2085 * On domain 0 we need to free up some physical memory that is
2017 2086 * usable for DMA. Since GRUB loaded the boot_archive, it is
2018 2087 * sitting in low MFN memory. We'll relocated the boot archive
2019 2088 * pages to high PFN memory.
2020 2089 */
2021 2090 if (DOMAIN_IS_INITDOMAIN(xen_info))
|
↓ open down ↓ |
330 lines elided |
↑ open up ↑ |
2022 2091 relocate_boot_archive(xbp);
2023 2092 #endif
2024 2093
2025 2094 #ifndef __xpv
2026 2095 /*
2027 2096 * Install an IDT to catch early pagefaults (shouldn't have any).
2028 2097 * Also needed for kmdb.
2029 2098 */
2030 2099 bop_idt_init();
2031 2100 #endif
2101 + /* Set up the shadow fb for framebuffer console */
2102 + boot_fb_shadow_init(bops);
2032 2103
2033 2104 /*
2034 2105 * Start building the boot properties from the command line
2035 2106 */
2036 2107 DBG_MSG("Initializing boot properties:\n");
2037 2108 build_boot_properties(xbp);
2038 2109
2039 2110 if (find_boot_prop("prom_debug") || kbm_debug) {
2040 2111 char *value;
2041 2112
2042 2113 value = do_bsys_alloc(NULL, NULL, MMU_PAGESIZE, MMU_PAGESIZE);
2043 2114 boot_prop_display(value);
2044 2115 }
2045 2116
2046 2117 /*
2047 2118 * jump into krtld...
2048 2119 */
2049 2120 _kobj_boot(&bop_sysp, NULL, bops, NULL);
2050 2121 }
2051 2122
2052 2123
2053 2124 /*ARGSUSED*/
2054 2125 static caddr_t
2055 2126 no_more_alloc(bootops_t *bop, caddr_t virthint, size_t size, int align)
2056 2127 {
2057 2128 panic("Attempt to bsys_alloc() too late\n");
2058 2129 return (NULL);
2059 2130 }
2060 2131
2061 2132 /*ARGSUSED*/
2062 2133 static void
2063 2134 no_more_free(bootops_t *bop, caddr_t virt, size_t size)
2064 2135 {
2065 2136 panic("Attempt to bsys_free() too late\n");
2066 2137 }
2067 2138
2068 2139 void
2069 2140 bop_no_more_mem(void)
2070 2141 {
2071 2142 DBG(total_bop_alloc_scratch);
2072 2143 DBG(total_bop_alloc_kernel);
2073 2144 bootops->bsys_alloc = no_more_alloc;
2074 2145 bootops->bsys_free = no_more_free;
2075 2146 }
2076 2147
2077 2148
2078 2149 /*
2079 2150 * Set ACPI firmware properties
2080 2151 */
2081 2152
2082 2153 static caddr_t
2083 2154 vmap_phys(size_t length, paddr_t pa)
2084 2155 {
2085 2156 paddr_t start, end;
2086 2157 caddr_t va;
2087 2158 size_t len, page;
2088 2159
2089 2160 #ifdef __xpv
2090 2161 pa = pfn_to_pa(xen_assign_pfn(mmu_btop(pa))) | (pa & MMU_PAGEOFFSET);
2091 2162 #endif
2092 2163 start = P2ALIGN(pa, MMU_PAGESIZE);
2093 2164 end = P2ROUNDUP(pa + length, MMU_PAGESIZE);
2094 2165 len = end - start;
2095 2166 va = (caddr_t)alloc_vaddr(len, MMU_PAGESIZE);
2096 2167 for (page = 0; page < len; page += MMU_PAGESIZE)
2097 2168 kbm_map((uintptr_t)va + page, start + page, 0, 0);
2098 2169 return (va + (pa & MMU_PAGEOFFSET));
2099 2170 }
2100 2171
2101 2172 static uint8_t
2102 2173 checksum_table(uint8_t *tp, size_t len)
2103 2174 {
2104 2175 uint8_t sum = 0;
2105 2176
2106 2177 while (len-- > 0)
2107 2178 sum += *tp++;
2108 2179
2109 2180 return (sum);
2110 2181 }
2111 2182
2112 2183 static int
2113 2184 valid_rsdp(ACPI_TABLE_RSDP *rp)
2114 2185 {
2115 2186
2116 2187 /* validate the V1.x checksum */
2117 2188 if (checksum_table((uint8_t *)rp, ACPI_RSDP_CHECKSUM_LENGTH) != 0)
2118 2189 return (0);
2119 2190
2120 2191 /* If pre-ACPI 2.0, this is a valid RSDP */
2121 2192 if (rp->Revision < 2)
2122 2193 return (1);
2123 2194
2124 2195 /* validate the V2.x checksum */
2125 2196 if (checksum_table((uint8_t *)rp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)
2126 2197 return (0);
2127 2198
2128 2199 return (1);
2129 2200 }
2130 2201
2131 2202 /*
2132 2203 * Scan memory range for an RSDP;
2133 2204 * see ACPI 3.0 Spec, 5.2.5.1
2134 2205 */
2135 2206 static ACPI_TABLE_RSDP *
2136 2207 scan_rsdp(paddr_t start, paddr_t end)
2137 2208 {
2138 2209 ssize_t len = end - start;
2139 2210 caddr_t ptr;
2140 2211
2141 2212 ptr = vmap_phys(len, start);
2142 2213 while (len > 0) {
2143 2214 if (strncmp(ptr, ACPI_SIG_RSDP, strlen(ACPI_SIG_RSDP)) == 0 &&
2144 2215 valid_rsdp((ACPI_TABLE_RSDP *)ptr))
2145 2216 return ((ACPI_TABLE_RSDP *)ptr);
2146 2217
2147 2218 ptr += ACPI_RSDP_SCAN_STEP;
2148 2219 len -= ACPI_RSDP_SCAN_STEP;
2149 2220 }
2150 2221
2151 2222 return (NULL);
2152 2223 }
2153 2224
2154 2225 /*
2155 2226 * Refer to ACPI 3.0 Spec, section 5.2.5.1 to understand this function
2156 2227 */
2157 2228 static ACPI_TABLE_RSDP *
2158 2229 find_rsdp()
2159 2230 {
2160 2231 ACPI_TABLE_RSDP *rsdp;
2161 2232 uint64_t rsdp_val = 0;
2162 2233 uint16_t *ebda_seg;
2163 2234 paddr_t ebda_addr;
2164 2235
2165 2236 /* check for "acpi-root-tab" property */
2166 2237 if (do_bsys_getproplen(NULL, "acpi-root-tab") == sizeof (uint64_t)) {
2167 2238 (void) do_bsys_getprop(NULL, "acpi-root-tab", &rsdp_val);
2168 2239 if (rsdp_val != 0) {
2169 2240 rsdp = scan_rsdp(rsdp_val, rsdp_val + sizeof (*rsdp));
2170 2241 if (rsdp != NULL) {
2171 2242 if (kbm_debug) {
2172 2243 bop_printf(NULL,
2173 2244 "Using RSDP from bootloader: "
2174 2245 "0x%p\n", (void *)rsdp);
2175 2246 }
2176 2247 return (rsdp);
2177 2248 }
2178 2249 }
2179 2250 }
2180 2251
2181 2252 /*
2182 2253 * Get the EBDA segment and scan the first 1K
2183 2254 */
2184 2255 ebda_seg = (uint16_t *)vmap_phys(sizeof (uint16_t),
2185 2256 ACPI_EBDA_PTR_LOCATION);
2186 2257 ebda_addr = *ebda_seg << 4;
2187 2258 rsdp = scan_rsdp(ebda_addr, ebda_addr + ACPI_EBDA_WINDOW_SIZE);
2188 2259 if (rsdp == NULL)
2189 2260 /* if EBDA doesn't contain RSDP, look in BIOS memory */
2190 2261 rsdp = scan_rsdp(ACPI_HI_RSDP_WINDOW_BASE,
2191 2262 ACPI_HI_RSDP_WINDOW_BASE + ACPI_HI_RSDP_WINDOW_SIZE);
2192 2263 return (rsdp);
2193 2264 }
2194 2265
2195 2266 static ACPI_TABLE_HEADER *
2196 2267 map_fw_table(paddr_t table_addr)
2197 2268 {
2198 2269 ACPI_TABLE_HEADER *tp;
2199 2270 size_t len = MAX(sizeof (*tp), MMU_PAGESIZE);
2200 2271
2201 2272 /*
2202 2273 * Map at least a page; if the table is larger than this, remap it
2203 2274 */
2204 2275 tp = (ACPI_TABLE_HEADER *)vmap_phys(len, table_addr);
2205 2276 if (tp->Length > len)
2206 2277 tp = (ACPI_TABLE_HEADER *)vmap_phys(tp->Length, table_addr);
2207 2278 return (tp);
2208 2279 }
2209 2280
2210 2281 static ACPI_TABLE_HEADER *
2211 2282 find_fw_table(char *signature)
2212 2283 {
2213 2284 static int revision = 0;
2214 2285 static ACPI_TABLE_XSDT *xsdt;
2215 2286 static int len;
2216 2287 paddr_t xsdt_addr;
2217 2288 ACPI_TABLE_RSDP *rsdp;
2218 2289 ACPI_TABLE_HEADER *tp;
2219 2290 paddr_t table_addr;
2220 2291 int n;
2221 2292
2222 2293 if (strlen(signature) != ACPI_NAME_SIZE)
2223 2294 return (NULL);
2224 2295
2225 2296 /*
2226 2297 * Reading the ACPI 3.0 Spec, section 5.2.5.3 will help
2227 2298 * understand this code. If we haven't already found the RSDT/XSDT,
2228 2299 * revision will be 0. Find the RSDP and check the revision
2229 2300 * to find out whether to use the RSDT or XSDT. If revision is
2230 2301 * 0 or 1, use the RSDT and set internal revision to 1; if it is 2,
2231 2302 * use the XSDT. If the XSDT address is 0, though, fall back to
2232 2303 * revision 1 and use the RSDT.
2233 2304 */
2234 2305 if (revision == 0) {
2235 2306 if ((rsdp = find_rsdp()) != NULL) {
2236 2307 revision = rsdp->Revision;
2237 2308 /*
2238 2309 * ACPI 6.0 states that current revision is 2
2239 2310 * from acpi_table_rsdp definition:
2240 2311 * Must be (0) for ACPI 1.0 or (2) for ACPI 2.0+
2241 2312 */
2242 2313 if (revision > 2)
2243 2314 revision = 2;
2244 2315 switch (revision) {
2245 2316 case 2:
2246 2317 /*
2247 2318 * Use the XSDT unless BIOS is buggy and
2248 2319 * claims to be rev 2 but has a null XSDT
2249 2320 * address
2250 2321 */
2251 2322 xsdt_addr = rsdp->XsdtPhysicalAddress;
2252 2323 if (xsdt_addr != 0)
2253 2324 break;
2254 2325 /* FALLTHROUGH */
2255 2326 case 0:
2256 2327 /* treat RSDP rev 0 as revision 1 internally */
2257 2328 revision = 1;
2258 2329 /* FALLTHROUGH */
2259 2330 case 1:
2260 2331 /* use the RSDT for rev 0/1 */
2261 2332 xsdt_addr = rsdp->RsdtPhysicalAddress;
2262 2333 break;
2263 2334 default:
2264 2335 /* unknown revision */
2265 2336 revision = 0;
2266 2337 break;
2267 2338 }
2268 2339 }
2269 2340 if (revision == 0)
2270 2341 return (NULL);
2271 2342
2272 2343 /* cache the XSDT info */
2273 2344 xsdt = (ACPI_TABLE_XSDT *)map_fw_table(xsdt_addr);
2274 2345 len = (xsdt->Header.Length - sizeof (xsdt->Header)) /
2275 2346 ((revision == 1) ? sizeof (uint32_t) : sizeof (uint64_t));
2276 2347 }
2277 2348
2278 2349 /*
2279 2350 * Scan the table headers looking for a signature match
2280 2351 */
2281 2352 for (n = 0; n < len; n++) {
2282 2353 ACPI_TABLE_RSDT *rsdt = (ACPI_TABLE_RSDT *)xsdt;
2283 2354 table_addr = (revision == 1) ? rsdt->TableOffsetEntry[n] :
2284 2355 xsdt->TableOffsetEntry[n];
2285 2356
2286 2357 if (table_addr == 0)
2287 2358 continue;
2288 2359 tp = map_fw_table(table_addr);
2289 2360 if (strncmp(tp->Signature, signature, ACPI_NAME_SIZE) == 0) {
2290 2361 return (tp);
2291 2362 }
2292 2363 }
2293 2364 return (NULL);
2294 2365 }
2295 2366
2296 2367 static void
2297 2368 process_mcfg(ACPI_TABLE_MCFG *tp)
2298 2369 {
2299 2370 ACPI_MCFG_ALLOCATION *cfg_baap;
2300 2371 char *cfg_baa_endp;
|
↓ open down ↓ |
259 lines elided |
↑ open up ↑ |
2301 2372 int64_t ecfginfo[4];
2302 2373
2303 2374 cfg_baap = (ACPI_MCFG_ALLOCATION *)((uintptr_t)tp + sizeof (*tp));
2304 2375 cfg_baa_endp = ((char *)tp) + tp->Header.Length;
2305 2376 while ((char *)cfg_baap < cfg_baa_endp) {
2306 2377 if (cfg_baap->Address != 0 && cfg_baap->PciSegment == 0) {
2307 2378 ecfginfo[0] = cfg_baap->Address;
2308 2379 ecfginfo[1] = cfg_baap->PciSegment;
2309 2380 ecfginfo[2] = cfg_baap->StartBusNumber;
2310 2381 ecfginfo[3] = cfg_baap->EndBusNumber;
2311 - bsetprop(MCFG_PROPNAME, strlen(MCFG_PROPNAME),
2382 + bsetprop(DDI_PROP_TYPE_INT64,
2383 + MCFG_PROPNAME, strlen(MCFG_PROPNAME),
2312 2384 ecfginfo, sizeof (ecfginfo));
2313 2385 break;
2314 2386 }
2315 2387 cfg_baap++;
2316 2388 }
2317 2389 }
2318 2390
2319 2391 #ifndef __xpv
2320 2392 static void
2321 2393 process_madt_entries(ACPI_TABLE_MADT *tp, uint32_t *cpu_countp,
2322 2394 uint32_t *cpu_possible_countp, uint32_t *cpu_apicid_array)
2323 2395 {
2324 2396 ACPI_SUBTABLE_HEADER *item, *end;
2325 2397 uint32_t cpu_count = 0;
2326 2398 uint32_t cpu_possible_count = 0;
2327 2399
2328 2400 /*
2329 2401 * Determine number of CPUs and keep track of "final" APIC ID
2330 2402 * for each CPU by walking through ACPI MADT processor list
2331 2403 */
2332 2404 end = (ACPI_SUBTABLE_HEADER *)(tp->Header.Length + (uintptr_t)tp);
2333 2405 item = (ACPI_SUBTABLE_HEADER *)((uintptr_t)tp + sizeof (*tp));
2334 2406
2335 2407 while (item < end) {
2336 2408 switch (item->Type) {
2337 2409 case ACPI_MADT_TYPE_LOCAL_APIC: {
2338 2410 ACPI_MADT_LOCAL_APIC *cpu =
2339 2411 (ACPI_MADT_LOCAL_APIC *) item;
2340 2412
2341 2413 if (cpu->LapicFlags & ACPI_MADT_ENABLED) {
2342 2414 if (cpu_apicid_array != NULL)
2343 2415 cpu_apicid_array[cpu_count] = cpu->Id;
2344 2416 cpu_count++;
2345 2417 }
2346 2418 cpu_possible_count++;
2347 2419 break;
2348 2420 }
2349 2421 case ACPI_MADT_TYPE_LOCAL_X2APIC: {
2350 2422 ACPI_MADT_LOCAL_X2APIC *cpu =
2351 2423 (ACPI_MADT_LOCAL_X2APIC *) item;
2352 2424
2353 2425 if (cpu->LapicFlags & ACPI_MADT_ENABLED) {
2354 2426 if (cpu_apicid_array != NULL)
2355 2427 cpu_apicid_array[cpu_count] =
2356 2428 cpu->LocalApicId;
2357 2429 cpu_count++;
2358 2430 }
2359 2431 cpu_possible_count++;
2360 2432 break;
2361 2433 }
2362 2434 default:
2363 2435 if (kbm_debug)
2364 2436 bop_printf(NULL, "MADT type %d\n", item->Type);
2365 2437 break;
2366 2438 }
2367 2439
2368 2440 item = (ACPI_SUBTABLE_HEADER *)((uintptr_t)item + item->Length);
2369 2441 }
2370 2442 if (cpu_countp)
2371 2443 *cpu_countp = cpu_count;
2372 2444 if (cpu_possible_countp)
2373 2445 *cpu_possible_countp = cpu_possible_count;
2374 2446 }
2375 2447
2376 2448 static void
2377 2449 process_madt(ACPI_TABLE_MADT *tp)
2378 2450 {
2379 2451 uint32_t cpu_count = 0;
2380 2452 uint32_t cpu_possible_count = 0;
2381 2453 uint32_t *cpu_apicid_array; /* x2APIC ID is 32bit! */
2382 2454
2383 2455 if (tp != NULL) {
2384 2456 /* count cpu's */
2385 2457 process_madt_entries(tp, &cpu_count, &cpu_possible_count, NULL);
2386 2458
2387 2459 cpu_apicid_array = (uint32_t *)do_bsys_alloc(NULL, NULL,
2388 2460 cpu_count * sizeof (*cpu_apicid_array), MMU_PAGESIZE);
|
↓ open down ↓ |
67 lines elided |
↑ open up ↑ |
2389 2461 if (cpu_apicid_array == NULL)
2390 2462 bop_panic("Not enough memory for APIC ID array");
2391 2463
2392 2464 /* copy IDs */
2393 2465 process_madt_entries(tp, NULL, NULL, cpu_apicid_array);
2394 2466
2395 2467 /*
2396 2468 * Make boot property for array of "final" APIC IDs for each
2397 2469 * CPU
2398 2470 */
2399 - bsetprop(BP_CPU_APICID_ARRAY, strlen(BP_CPU_APICID_ARRAY),
2471 + bsetprop(DDI_PROP_TYPE_INT,
2472 + BP_CPU_APICID_ARRAY, strlen(BP_CPU_APICID_ARRAY),
2400 2473 cpu_apicid_array, cpu_count * sizeof (*cpu_apicid_array));
2401 2474 }
2402 2475
2403 2476 /*
2404 2477 * Check whether property plat-max-ncpus is already set.
2405 2478 */
2406 2479 if (do_bsys_getproplen(NULL, PLAT_MAX_NCPUS_NAME) < 0) {
2407 2480 /*
2408 2481 * Set plat-max-ncpus to number of maximum possible CPUs given
2409 2482 * in MADT if it hasn't been set.
2410 2483 * There's no formal way to detect max possible CPUs supported
2411 2484 * by platform according to ACPI spec3.0b. So current CPU
2412 2485 * hotplug implementation expects that all possible CPUs will
2413 2486 * have an entry in MADT table and set plat-max-ncpus to number
2414 2487 * of entries in MADT.
2415 2488 * With introducing of ACPI4.0, Maximum System Capability Table
2416 2489 * (MSCT) provides maximum number of CPUs supported by platform.
2417 2490 * If MSCT is unavailable, fall back to old way.
2418 2491 */
2419 2492 if (tp != NULL)
2420 2493 bsetpropsi(PLAT_MAX_NCPUS_NAME, cpu_possible_count);
2421 2494 }
2422 2495
2423 2496 /*
2424 2497 * Set boot property boot-max-ncpus to number of CPUs existing at
2425 2498 * boot time. boot-max-ncpus is mainly used for optimization.
2426 2499 */
2427 2500 if (tp != NULL)
2428 2501 bsetpropsi(BOOT_MAX_NCPUS_NAME, cpu_count);
2429 2502
2430 2503 /*
2431 2504 * User-set boot-ncpus overrides firmware count
2432 2505 */
2433 2506 if (do_bsys_getproplen(NULL, BOOT_NCPUS_NAME) >= 0)
2434 2507 return;
2435 2508
2436 2509 /*
2437 2510 * Set boot property boot-ncpus to number of active CPUs given in MADT
2438 2511 * if it hasn't been set yet.
2439 2512 */
2440 2513 if (tp != NULL)
2441 2514 bsetpropsi(BOOT_NCPUS_NAME, cpu_count);
2442 2515 }
2443 2516
2444 2517 static void
2445 2518 process_srat(ACPI_TABLE_SRAT *tp)
2446 2519 {
2447 2520 ACPI_SUBTABLE_HEADER *item, *end;
2448 2521 int i;
2449 2522 int proc_num, mem_num;
2450 2523 #pragma pack(1)
2451 2524 struct {
2452 2525 uint32_t domain;
2453 2526 uint32_t apic_id;
2454 2527 uint32_t sapic_id;
2455 2528 } processor;
2456 2529 struct {
2457 2530 uint32_t domain;
2458 2531 uint32_t x2apic_id;
2459 2532 } x2apic;
2460 2533 struct {
2461 2534 uint32_t domain;
2462 2535 uint64_t addr;
2463 2536 uint64_t length;
2464 2537 uint32_t flags;
2465 2538 } memory;
2466 2539 #pragma pack()
2467 2540 char prop_name[30];
2468 2541 uint64_t maxmem = 0;
2469 2542
2470 2543 if (tp == NULL)
2471 2544 return;
2472 2545
2473 2546 proc_num = mem_num = 0;
2474 2547 end = (ACPI_SUBTABLE_HEADER *)(tp->Header.Length + (uintptr_t)tp);
2475 2548 item = (ACPI_SUBTABLE_HEADER *)((uintptr_t)tp + sizeof (*tp));
2476 2549 while (item < end) {
2477 2550 switch (item->Type) {
2478 2551 case ACPI_SRAT_TYPE_CPU_AFFINITY: {
2479 2552 ACPI_SRAT_CPU_AFFINITY *cpu =
2480 2553 (ACPI_SRAT_CPU_AFFINITY *) item;
2481 2554
|
↓ open down ↓ |
72 lines elided |
↑ open up ↑ |
2482 2555 if (!(cpu->Flags & ACPI_SRAT_CPU_ENABLED))
2483 2556 break;
2484 2557 processor.domain = cpu->ProximityDomainLo;
2485 2558 for (i = 0; i < 3; i++)
2486 2559 processor.domain +=
2487 2560 cpu->ProximityDomainHi[i] << ((i + 1) * 8);
2488 2561 processor.apic_id = cpu->ApicId;
2489 2562 processor.sapic_id = cpu->LocalSapicEid;
2490 2563 (void) snprintf(prop_name, 30, "acpi-srat-processor-%d",
2491 2564 proc_num);
2492 - bsetprop(prop_name, strlen(prop_name), &processor,
2565 + bsetprop(DDI_PROP_TYPE_INT,
2566 + prop_name, strlen(prop_name), &processor,
2493 2567 sizeof (processor));
2494 2568 proc_num++;
2495 2569 break;
2496 2570 }
2497 2571 case ACPI_SRAT_TYPE_MEMORY_AFFINITY: {
2498 2572 ACPI_SRAT_MEM_AFFINITY *mem =
2499 2573 (ACPI_SRAT_MEM_AFFINITY *)item;
2500 2574
2501 2575 if (!(mem->Flags & ACPI_SRAT_MEM_ENABLED))
2502 2576 break;
2503 2577 memory.domain = mem->ProximityDomain;
2504 2578 memory.addr = mem->BaseAddress;
2505 2579 memory.length = mem->Length;
2506 2580 memory.flags = mem->Flags;
2507 2581 (void) snprintf(prop_name, 30, "acpi-srat-memory-%d",
2508 2582 mem_num);
2509 - bsetprop(prop_name, strlen(prop_name), &memory,
2583 + bsetprop(DDI_PROP_TYPE_INT,
2584 + prop_name, strlen(prop_name), &memory,
2510 2585 sizeof (memory));
2511 2586 if ((mem->Flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) &&
2512 2587 (memory.addr + memory.length > maxmem)) {
2513 2588 maxmem = memory.addr + memory.length;
2514 2589 }
2515 2590 mem_num++;
2516 2591 break;
2517 2592 }
2518 2593 case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY: {
2519 2594 ACPI_SRAT_X2APIC_CPU_AFFINITY *x2cpu =
2520 2595 (ACPI_SRAT_X2APIC_CPU_AFFINITY *) item;
2521 2596
2522 2597 if (!(x2cpu->Flags & ACPI_SRAT_CPU_ENABLED))
2523 2598 break;
2524 2599 x2apic.domain = x2cpu->ProximityDomain;
2525 2600 x2apic.x2apic_id = x2cpu->ApicId;
2526 2601 (void) snprintf(prop_name, 30, "acpi-srat-processor-%d",
2527 2602 proc_num);
2528 - bsetprop(prop_name, strlen(prop_name), &x2apic,
2603 + bsetprop(DDI_PROP_TYPE_INT,
2604 + prop_name, strlen(prop_name), &x2apic,
2529 2605 sizeof (x2apic));
2530 2606 proc_num++;
2531 2607 break;
2532 2608 }
2533 2609 default:
2534 2610 if (kbm_debug)
2535 2611 bop_printf(NULL, "SRAT type %d\n", item->Type);
2536 2612 break;
2537 2613 }
2538 2614
2539 2615 item = (ACPI_SUBTABLE_HEADER *)
2540 2616 (item->Length + (uintptr_t)item);
2541 2617 }
2542 2618
2543 2619 /*
2544 2620 * The maximum physical address calculated from the SRAT table is more
2545 2621 * accurate than that calculated from the MSCT table.
2546 2622 */
2547 2623 if (maxmem != 0) {
2548 2624 plat_dr_physmax = btop(maxmem);
2549 2625 }
2550 2626 }
2551 2627
2552 2628 static void
2553 2629 process_slit(ACPI_TABLE_SLIT *tp)
2554 2630 {
2555 2631
2556 2632 /*
2557 2633 * Check the number of localities; if it's too huge, we just
2558 2634 * return and locality enumeration code will handle this later,
|
↓ open down ↓ |
20 lines elided |
↑ open up ↑ |
2559 2635 * if possible.
2560 2636 *
2561 2637 * Note that the size of the table is the square of the
2562 2638 * number of localities; if the number of localities exceeds
2563 2639 * UINT16_MAX, the table size may overflow an int when being
2564 2640 * passed to bsetprop() below.
2565 2641 */
2566 2642 if (tp->LocalityCount >= SLIT_LOCALITIES_MAX)
2567 2643 return;
2568 2644
2569 - bsetprop(SLIT_NUM_PROPNAME, strlen(SLIT_NUM_PROPNAME),
2570 - &tp->LocalityCount, sizeof (tp->LocalityCount));
2571 - bsetprop(SLIT_PROPNAME, strlen(SLIT_PROPNAME), &tp->Entry,
2645 + bsetprop64(SLIT_NUM_PROPNAME, tp->LocalityCount);
2646 + bsetprop(DDI_PROP_TYPE_BYTE,
2647 + SLIT_PROPNAME, strlen(SLIT_PROPNAME), &tp->Entry,
2572 2648 tp->LocalityCount * tp->LocalityCount);
2573 2649 }
2574 2650
2575 2651 static ACPI_TABLE_MSCT *
2576 2652 process_msct(ACPI_TABLE_MSCT *tp)
2577 2653 {
2578 2654 int last_seen = 0;
2579 2655 int proc_num = 0;
2580 2656 ACPI_MSCT_PROXIMITY *item, *end;
2581 2657 extern uint64_t plat_dr_options;
2582 2658
2583 2659 ASSERT(tp != NULL);
2584 2660
2585 2661 end = (ACPI_MSCT_PROXIMITY *)(tp->Header.Length + (uintptr_t)tp);
2586 2662 for (item = (void *)((uintptr_t)tp + tp->ProximityOffset);
2587 2663 item < end;
2588 2664 item = (void *)(item->Length + (uintptr_t)item)) {
2589 2665 /*
2590 2666 * Sanity check according to section 5.2.19.1 of ACPI 4.0.
2591 2667 * Revision 1
2592 2668 * Length 22
2593 2669 */
2594 2670 if (item->Revision != 1 || item->Length != 22) {
2595 2671 cmn_err(CE_CONT,
2596 2672 "?boot: unknown proximity domain structure in MSCT "
2597 2673 "with Revision(%d), Length(%d).\n",
2598 2674 (int)item->Revision, (int)item->Length);
2599 2675 return (NULL);
2600 2676 } else if (item->RangeStart > item->RangeEnd) {
2601 2677 cmn_err(CE_CONT,
2602 2678 "?boot: invalid proximity domain structure in MSCT "
2603 2679 "with RangeStart(%u), RangeEnd(%u).\n",
2604 2680 item->RangeStart, item->RangeEnd);
2605 2681 return (NULL);
2606 2682 } else if (item->RangeStart != last_seen) {
2607 2683 /*
2608 2684 * Items must be organized in ascending order of the
2609 2685 * proximity domain enumerations.
2610 2686 */
2611 2687 cmn_err(CE_CONT,
2612 2688 "?boot: invalid proximity domain structure in MSCT,"
2613 2689 " items are not orginized in ascending order.\n");
2614 2690 return (NULL);
2615 2691 }
2616 2692
2617 2693 /*
2618 2694 * If ProcessorCapacity is 0 then there would be no CPUs in this
2619 2695 * domain.
2620 2696 */
2621 2697 if (item->ProcessorCapacity != 0) {
2622 2698 proc_num += (item->RangeEnd - item->RangeStart + 1) *
2623 2699 item->ProcessorCapacity;
2624 2700 }
2625 2701
2626 2702 last_seen = item->RangeEnd - item->RangeStart + 1;
2627 2703 /*
2628 2704 * Break out if all proximity domains have been processed.
2629 2705 * Some BIOSes may have unused items at the end of MSCT table.
2630 2706 */
2631 2707 if (last_seen > tp->MaxProximityDomains) {
2632 2708 break;
2633 2709 }
2634 2710 }
2635 2711 if (last_seen != tp->MaxProximityDomains + 1) {
2636 2712 cmn_err(CE_CONT,
2637 2713 "?boot: invalid proximity domain structure in MSCT, "
2638 2714 "proximity domain count doesn't match.\n");
2639 2715 return (NULL);
2640 2716 }
2641 2717
2642 2718 /*
2643 2719 * Set plat-max-ncpus property if it hasn't been set yet.
2644 2720 */
2645 2721 if (do_bsys_getproplen(NULL, PLAT_MAX_NCPUS_NAME) < 0) {
2646 2722 if (proc_num != 0) {
2647 2723 bsetpropsi(PLAT_MAX_NCPUS_NAME, proc_num);
2648 2724 }
2649 2725 }
2650 2726
2651 2727 /*
2652 2728 * Use Maximum Physical Address from the MSCT table as upper limit for
2653 2729 * memory hot-adding by default. It may be overridden by value from
2654 2730 * the SRAT table or the "plat-dr-physmax" boot option.
2655 2731 */
2656 2732 plat_dr_physmax = btop(tp->MaxAddress + 1);
2657 2733
2658 2734 /*
2659 2735 * Existence of MSCT implies CPU/memory hotplug-capability for the
2660 2736 * platform.
2661 2737 */
2662 2738 plat_dr_options |= PLAT_DR_FEATURE_CPU;
2663 2739 plat_dr_options |= PLAT_DR_FEATURE_MEMORY;
2664 2740
2665 2741 return (tp);
2666 2742 }
2667 2743
2668 2744 #else /* __xpv */
2669 2745 static void
2670 2746 enumerate_xen_cpus()
2671 2747 {
2672 2748 processorid_t id, max_id;
2673 2749
2674 2750 /*
2675 2751 * User-set boot-ncpus overrides enumeration
2676 2752 */
2677 2753 if (do_bsys_getproplen(NULL, BOOT_NCPUS_NAME) >= 0)
2678 2754 return;
2679 2755
2680 2756 /*
2681 2757 * Probe every possible virtual CPU id and remember the
2682 2758 * highest id present; the count of CPUs is one greater
2683 2759 * than this. This tacitly assumes at least cpu 0 is present.
2684 2760 */
2685 2761 max_id = 0;
2686 2762 for (id = 0; id < MAX_VIRT_CPUS; id++)
2687 2763 if (HYPERVISOR_vcpu_op(VCPUOP_is_up, id, NULL) == 0)
2688 2764 max_id = id;
2689 2765
2690 2766 bsetpropsi(BOOT_NCPUS_NAME, max_id+1);
2691 2767
2692 2768 }
2693 2769 #endif /* __xpv */
2694 2770
2695 2771 /*ARGSUSED*/
2696 2772 static void
2697 2773 build_firmware_properties(struct xboot_info *xbp)
2698 2774 {
2699 2775 ACPI_TABLE_HEADER *tp = NULL;
2700 2776
2701 2777 #ifndef __xpv
2702 2778 if (xbp->bi_uefi_arch == XBI_UEFI_ARCH_64) {
2703 2779 bsetprops("efi-systype", "64");
2704 2780 bsetprop64("efi-systab",
2705 2781 (uint64_t)(uintptr_t)xbp->bi_uefi_systab);
2706 2782 if (kbm_debug)
2707 2783 bop_printf(NULL, "64-bit UEFI detected.\n");
2708 2784 } else if (xbp->bi_uefi_arch == XBI_UEFI_ARCH_32) {
2709 2785 bsetprops("efi-systype", "32");
2710 2786 bsetprop64("efi-systab",
2711 2787 (uint64_t)(uintptr_t)xbp->bi_uefi_systab);
2712 2788 if (kbm_debug)
2713 2789 bop_printf(NULL, "32-bit UEFI detected.\n");
2714 2790 }
2715 2791
2716 2792 if (xbp->bi_acpi_rsdp != NULL) {
2717 2793 bsetprop64("acpi-root-tab",
2718 2794 (uint64_t)(uintptr_t)xbp->bi_acpi_rsdp);
2719 2795 }
2720 2796
2721 2797 if (xbp->bi_smbios != NULL) {
2722 2798 bsetprop64("smbios-address",
2723 2799 (uint64_t)(uintptr_t)xbp->bi_smbios);
2724 2800 }
2725 2801
2726 2802 if ((tp = find_fw_table(ACPI_SIG_MSCT)) != NULL)
2727 2803 msct_ptr = process_msct((ACPI_TABLE_MSCT *)tp);
2728 2804 else
2729 2805 msct_ptr = NULL;
2730 2806
2731 2807 if ((tp = find_fw_table(ACPI_SIG_MADT)) != NULL)
2732 2808 process_madt((ACPI_TABLE_MADT *)tp);
2733 2809
2734 2810 if ((srat_ptr = (ACPI_TABLE_SRAT *)
2735 2811 find_fw_table(ACPI_SIG_SRAT)) != NULL)
2736 2812 process_srat(srat_ptr);
2737 2813
2738 2814 if (slit_ptr = (ACPI_TABLE_SLIT *)find_fw_table(ACPI_SIG_SLIT))
2739 2815 process_slit(slit_ptr);
2740 2816
2741 2817 tp = find_fw_table(ACPI_SIG_MCFG);
2742 2818 #else /* __xpv */
2743 2819 enumerate_xen_cpus();
2744 2820 if (DOMAIN_IS_INITDOMAIN(xen_info))
2745 2821 tp = find_fw_table(ACPI_SIG_MCFG);
2746 2822 #endif /* __xpv */
2747 2823 if (tp != NULL)
2748 2824 process_mcfg((ACPI_TABLE_MCFG *)tp);
2749 2825 }
2750 2826
2751 2827 /*
2752 2828 * fake up a boot property for deferred early console output
|
↓ open down ↓ |
171 lines elided |
↑ open up ↑ |
2753 2829 * this is used by both graphical boot and the (developer only)
2754 2830 * USB serial console
2755 2831 */
2756 2832 void *
2757 2833 defcons_init(size_t size)
2758 2834 {
2759 2835 static char *p = NULL;
2760 2836
2761 2837 p = do_bsys_alloc(NULL, NULL, size, MMU_PAGESIZE);
2762 2838 *p = 0;
2763 - bsetprop("deferred-console-buf", strlen("deferred-console-buf") + 1,
2764 - &p, sizeof (p));
2839 + bsetprop32("deferred-console-buf", (uint32_t)((uintptr_t)&p));
2765 2840 return (p);
2766 2841 }
2767 2842
2768 2843 /*ARGSUSED*/
2769 2844 int
2770 2845 boot_compinfo(int fd, struct compinfo *cbp)
2771 2846 {
2772 2847 cbp->iscmp = 0;
2773 2848 cbp->blksize = MAXBSIZE;
2774 2849 return (0);
2775 2850 }
2776 2851
2777 2852 #define BP_MAX_STRLEN 32
2778 2853
2779 2854 /*
2780 2855 * Get value for given boot property
2781 2856 */
2782 2857 int
2783 2858 bootprop_getval(const char *prop_name, u_longlong_t *prop_value)
2784 2859 {
2785 2860 int boot_prop_len;
2786 2861 char str[BP_MAX_STRLEN];
2787 2862 u_longlong_t value;
2788 2863
2789 2864 boot_prop_len = BOP_GETPROPLEN(bootops, prop_name);
2790 2865 if (boot_prop_len < 0 || boot_prop_len > sizeof (str) ||
2791 2866 BOP_GETPROP(bootops, prop_name, str) < 0 ||
2792 2867 kobj_getvalue(str, &value) == -1)
2793 2868 return (-1);
2794 2869
2795 2870 if (prop_value)
2796 2871 *prop_value = value;
2797 2872
2798 2873 return (0);
2799 2874 }
|
↓ open down ↓ |
25 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX