155d9950aSThomas Huth /*
255d9950aSThomas Huth * Common Hardware Reference Platform NVRAM helper functions.
355d9950aSThomas Huth *
455d9950aSThomas Huth * The CHRP NVRAM layout is used by OpenBIOS and SLOF. See CHRP
555d9950aSThomas Huth * specification, chapter 8, or the LoPAPR specification for details
655d9950aSThomas Huth * about the NVRAM layout.
755d9950aSThomas Huth *
855d9950aSThomas Huth * This code is free software; you can redistribute it and/or modify
955d9950aSThomas Huth * it under the terms of the GNU General Public License as published
1055d9950aSThomas Huth * by the Free Software Foundation; either version 2 of the License,
1155d9950aSThomas Huth * or (at your option) any later version.
1255d9950aSThomas Huth *
1355d9950aSThomas Huth * This program is distributed in the hope that it will be useful,
1455d9950aSThomas Huth * but WITHOUT ANY WARRANTY; without even the implied warranty of
1555d9950aSThomas Huth * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1655d9950aSThomas Huth * GNU General Public License for more details.
1755d9950aSThomas Huth *
1855d9950aSThomas Huth * You should have received a copy of the GNU General Public License
1955d9950aSThomas Huth * along with this program; if not, see <http://www.gnu.org/licenses/>.
2055d9950aSThomas Huth */
2155d9950aSThomas Huth
2255d9950aSThomas Huth #include "qemu/osdep.h"
2355d9950aSThomas Huth #include "qemu/cutils.h"
24*37035df5SGreg Kurz #include "qemu/error-report.h"
2555d9950aSThomas Huth #include "hw/nvram/chrp_nvram.h"
2655d9950aSThomas Huth #include "sysemu/sysemu.h"
2755d9950aSThomas Huth
chrp_nvram_set_var(uint8_t * nvram,int addr,const char * str,int max_len)28*37035df5SGreg Kurz static int chrp_nvram_set_var(uint8_t *nvram, int addr, const char *str,
29*37035df5SGreg Kurz int max_len)
30ad723fe5SThomas Huth {
31ad723fe5SThomas Huth int len;
32ad723fe5SThomas Huth
33ad723fe5SThomas Huth len = strlen(str) + 1;
34*37035df5SGreg Kurz
35*37035df5SGreg Kurz if (max_len < len) {
36*37035df5SGreg Kurz return -1;
37*37035df5SGreg Kurz }
38*37035df5SGreg Kurz
39ad723fe5SThomas Huth memcpy(&nvram[addr], str, len);
40ad723fe5SThomas Huth
41ad723fe5SThomas Huth return addr + len;
42ad723fe5SThomas Huth }
43ad723fe5SThomas Huth
4455d9950aSThomas Huth /**
4555d9950aSThomas Huth * Create a "system partition", used for the Open Firmware
4655d9950aSThomas Huth * environment variables.
4755d9950aSThomas Huth */
chrp_nvram_create_system_partition(uint8_t * data,int min_len,int max_len)48*37035df5SGreg Kurz int chrp_nvram_create_system_partition(uint8_t *data, int min_len, int max_len)
4955d9950aSThomas Huth {
50ad723fe5SThomas Huth ChrpNvramPartHdr *part_header;
5155d9950aSThomas Huth unsigned int i;
5255d9950aSThomas Huth int end;
5355d9950aSThomas Huth
54*37035df5SGreg Kurz if (max_len < sizeof(*part_header)) {
55*37035df5SGreg Kurz goto fail;
56*37035df5SGreg Kurz }
57*37035df5SGreg Kurz
58ad723fe5SThomas Huth part_header = (ChrpNvramPartHdr *)data;
59ad723fe5SThomas Huth part_header->signature = CHRP_NVPART_SYSTEM;
6055d9950aSThomas Huth pstrcpy(part_header->name, sizeof(part_header->name), "system");
6155d9950aSThomas Huth
62ad723fe5SThomas Huth end = sizeof(ChrpNvramPartHdr);
6355d9950aSThomas Huth for (i = 0; i < nb_prom_envs; i++) {
64*37035df5SGreg Kurz end = chrp_nvram_set_var(data, end, prom_envs[i], max_len - end);
65*37035df5SGreg Kurz if (end == -1) {
66*37035df5SGreg Kurz goto fail;
67*37035df5SGreg Kurz }
6855d9950aSThomas Huth }
6955d9950aSThomas Huth
7055d9950aSThomas Huth /* End marker */
7155d9950aSThomas Huth data[end++] = '\0';
7255d9950aSThomas Huth
7355d9950aSThomas Huth end = (end + 15) & ~15;
7455d9950aSThomas Huth /* XXX: OpenBIOS is not able to grow up a partition. Leave some space for
7555d9950aSThomas Huth new variables. */
7655d9950aSThomas Huth if (end < min_len) {
7755d9950aSThomas Huth end = min_len;
7855d9950aSThomas Huth }
79ad723fe5SThomas Huth chrp_nvram_finish_partition(part_header, end);
8055d9950aSThomas Huth
8155d9950aSThomas Huth return end;
82*37035df5SGreg Kurz
83*37035df5SGreg Kurz fail:
84*37035df5SGreg Kurz error_report("NVRAM is too small. Try to pass less data to -prom-env");
85*37035df5SGreg Kurz exit(EXIT_FAILURE);
8655d9950aSThomas Huth }
8755d9950aSThomas Huth
8855d9950aSThomas Huth /**
8955d9950aSThomas Huth * Create a "free space" partition
9055d9950aSThomas Huth */
chrp_nvram_create_free_partition(uint8_t * data,int len)9155d9950aSThomas Huth int chrp_nvram_create_free_partition(uint8_t *data, int len)
9255d9950aSThomas Huth {
93ad723fe5SThomas Huth ChrpNvramPartHdr *part_header;
9455d9950aSThomas Huth
95ad723fe5SThomas Huth part_header = (ChrpNvramPartHdr *)data;
96ad723fe5SThomas Huth part_header->signature = CHRP_NVPART_FREE;
9755d9950aSThomas Huth pstrcpy(part_header->name, sizeof(part_header->name), "free");
9855d9950aSThomas Huth
99ad723fe5SThomas Huth chrp_nvram_finish_partition(part_header, len);
10055d9950aSThomas Huth
10155d9950aSThomas Huth return len;
10255d9950aSThomas Huth }
103