xref: /openbmc/qemu/hw/nvram/chrp_nvram.c (revision dd8014e4e904e895435aae9f11a686f072762782)
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