blob: 481153d6850aebbe417c1f0f7e1d13ccb612ac58 [file] [log] [blame]
Aaron Durbin716738a2013-05-10 00:33:32 -05001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2013 Google, Inc.
5 *
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.
9 *
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.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include <string.h>
21#include <stddef.h>
22#include <console/console.h>
23#include <cbmem.h>
Stefan Reinauerfd4f4132013-06-19 12:25:44 -070024#include <arch/early_variables.h>
Aaron Durbin716738a2013-05-10 00:33:32 -050025
26typedef void (* const car_migration_func_t)(void);
27
28extern car_migration_func_t _car_migrate_start;
29extern car_migration_func_t _car_migrate_end;
30
31extern char _car_data_start[];
32extern char _car_data_end[];
33
34/*
35 * The car_migrated global variable determines if the cache-as-ram space has
Martin Roth4c3ab732013-07-08 16:23:54 -060036 * been migrated to real RAM. It does this by assuming the following things:
Aaron Durbin716738a2013-05-10 00:33:32 -050037 * 1. cache-as-ram space is zero'd out once it is set up.
38 * 2. Either the cache-as-ram space is memory-backed after getting torn down
39 * or the space returns 0xff's for each byte read.
40 * Based on these 2 attributes there is the ability to tell when the
41 * cache-as-ram region has been migrated.
42 */
43static int car_migrated CAR_GLOBAL;
44
45
46void *car_get_var_ptr(void *var)
47{
48 char *migrated_base;
49 int offset;
50 void * _car_start = &_car_data_start;
51 void * _car_end = &_car_data_end;
52
53 /* If the cache-as-ram has not been migrated return the pointer
54 * passed in. */
55 if (!car_migrated)
56 return var;
57
58 if (var < _car_start || var >= _car_end) {
59 printk(BIOS_ERR,
60 "Requesting CAR variable outside of CAR region: %p\n",
61 var);
62 return var;
63 }
64
65 migrated_base = cbmem_find(CBMEM_ID_CAR_GLOBALS);
66
67 if (migrated_base == NULL) {
68 printk(BIOS_ERR, "CAR: Could not find migration base!\n");
69 return var;
70 }
71
72 offset = (char *)var - (char *)_car_start;
73
74 return &migrated_base[offset];
75}
76
77void car_migrate_variables(void)
78{
79 void *migrated_base;
80 car_migration_func_t *migrate_func;
81 size_t car_data_size = &_car_data_end[0] - &_car_data_start[0];
82
Aaron Durbin7f5897a2013-06-21 18:02:26 +030083 /* Check if already migrated. */
84 if (car_migrated)
85 return;
86
Aaron Durbin716738a2013-05-10 00:33:32 -050087 migrated_base = cbmem_add(CBMEM_ID_CAR_GLOBALS, car_data_size);
88
89 if (migrated_base == NULL) {
90 printk(BIOS_ERR, "Could not migrate CAR data!\n");
91 return;
92 }
93
94 memcpy(migrated_base, &_car_data_start[0], car_data_size);
95
96 /* Mark that the data has been moved. */
97 car_migrated = ~0;
98
99 /* Call all the migration functions. */
100 migrate_func = &_car_migrate_start;
101 while (migrate_func != &_car_migrate_end) {
102 (*migrate_func)();
103 migrate_func++;
104 }
105}