2 * This file is part of the coreboot project.
4 * Copyright 2016 Google Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
18 #include <console/console.h>
19 #include <cpu/x86/msr.h>
20 #include <cpu/x86/mtrr.h>
21 #include <program_loading.h>
24 static inline void stack_push(struct postcar_frame
*pcf
, uint32_t val
)
28 pcf
->stack
-= sizeof(val
);
29 ptr
= (void *)pcf
->stack
;
33 int postcar_frame_init(struct postcar_frame
*pcf
, size_t stack_size
)
38 msr
= rdmsr(MTRR_CAP_MSR
);
40 stack
= cbmem_add(CBMEM_ID_ROMSTAGE_RAM_STACK
, stack_size
);
42 printk(BIOS_ERR
, "Couldn't add %zd byte stack in cbmem.\n",
47 pcf
->stack
= (uintptr_t)stack
;
48 pcf
->stack
+= stack_size
;
50 pcf
->upper_mask
= (1 << (cpu_phys_address_size() - 32)) - 1;
52 pcf
->max_var_mttrs
= msr
.lo
& MTRR_CAP_VCNT
;
54 pcf
->num_var_mttrs
= 0;
59 void postcar_frame_add_mtrr(struct postcar_frame
*pcf
,
60 uintptr_t addr
, size_t size
, int type
)
64 if (pcf
->num_var_mttrs
>= pcf
->max_var_mttrs
) {
65 printk(BIOS_ERR
, "No more variable MTRRs: %d\n",
70 /* Determine address alignment by lowest bit set in address. */
71 align
= addr
& (addr
^ (addr
- 1));
74 printk(BIOS_ERR
, "Address (%lx) alignment (%zx) < size (%zx)\n",
79 /* Push MTRR mask then base -- upper 32-bits then lower 32-bits. */
80 stack_push(pcf
, pcf
->upper_mask
);
81 stack_push(pcf
, ~(size
- 1) | MTRR_PHYS_MASK_VALID
);
83 stack_push(pcf
, addr
| type
);
87 void run_postcar_phase(struct postcar_frame
*pcf
)
90 PROG_INIT(PROG_UNKNOWN
, CONFIG_CBFS_PREFIX
"/postcar");
91 struct rmod_stage_load rsl
= {
92 .cbmem_id
= CBMEM_ID_AFTER_CAR
,
97 * Place the number of used variable MTRRs on stack then max number
98 * of variable MTRRs supported in the system.
100 stack_push(pcf
, pcf
->num_var_mttrs
);
101 stack_push(pcf
, pcf
->max_var_mttrs
);
103 if (prog_locate(&prog
))
104 die("Failed to locate after CAR program.\n");
105 if (rmodule_stage_load(&rsl
))
106 die("Failed to load after CAR program.\n");
108 /* Set the stack pointer within parameters of the program loaded. */
109 if (rsl
.params
== NULL
)
110 die("No parameters found in after CAR program.\n");
112 *(uintptr_t *)rsl
.params
= pcf
->stack
;
115 * Signal to rest of system that another update was made to the
116 * postcar program prior to running it.
118 prog_segment_loaded((uintptr_t)rsl
.params
, sizeof(uintptr_t),