diff options
Diffstat (limited to 'hw/nvram/chrp_nvram.c')
-rw-r--r-- | hw/nvram/chrp_nvram.c | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/hw/nvram/chrp_nvram.c b/hw/nvram/chrp_nvram.c new file mode 100644 index 000000000..d4d10a7c0 --- /dev/null +++ b/hw/nvram/chrp_nvram.c @@ -0,0 +1,102 @@ +/* + * Common Hardware Reference Platform NVRAM helper functions. + * + * The CHRP NVRAM layout is used by OpenBIOS and SLOF. See CHRP + * specification, chapter 8, or the LoPAPR specification for details + * about the NVRAM layout. + * + * This code is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation; either version 2 of the License, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "qemu/osdep.h" +#include "qemu/cutils.h" +#include "qemu/error-report.h" +#include "hw/nvram/chrp_nvram.h" +#include "sysemu/sysemu.h" + +static int chrp_nvram_set_var(uint8_t *nvram, int addr, const char *str, + int max_len) +{ + int len; + + len = strlen(str) + 1; + + if (max_len < len) { + return -1; + } + + memcpy(&nvram[addr], str, len); + + return addr + len; +} + +/** + * Create a "system partition", used for the Open Firmware + * environment variables. + */ +int chrp_nvram_create_system_partition(uint8_t *data, int min_len, int max_len) +{ + ChrpNvramPartHdr *part_header; + unsigned int i; + int end; + + if (max_len < sizeof(*part_header)) { + goto fail; + } + + part_header = (ChrpNvramPartHdr *)data; + part_header->signature = CHRP_NVPART_SYSTEM; + pstrcpy(part_header->name, sizeof(part_header->name), "system"); + + end = sizeof(ChrpNvramPartHdr); + for (i = 0; i < nb_prom_envs; i++) { + end = chrp_nvram_set_var(data, end, prom_envs[i], max_len - end); + if (end == -1) { + goto fail; + } + } + + /* End marker */ + data[end++] = '\0'; + + end = (end + 15) & ~15; + /* XXX: OpenBIOS is not able to grow up a partition. Leave some space for + new variables. */ + if (end < min_len) { + end = min_len; + } + chrp_nvram_finish_partition(part_header, end); + + return end; + +fail: + error_report("NVRAM is too small. Try to pass less data to -prom-env"); + exit(EXIT_FAILURE); +} + +/** + * Create a "free space" partition + */ +int chrp_nvram_create_free_partition(uint8_t *data, int len) +{ + ChrpNvramPartHdr *part_header; + + part_header = (ChrpNvramPartHdr *)data; + part_header->signature = CHRP_NVPART_FREE; + pstrcpy(part_header->name, sizeof(part_header->name), "free"); + + chrp_nvram_finish_partition(part_header, len); + + return len; +} |