Clone a tag rather than SeaBIOS stable branch HEAD
[coreboot.git] / payloads / bayou / config.c
1 /*
2  * This file is part of the bayou project.
3  *
4  * Copyright (C) 2008 Advanced Micro Devices, 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 version 2 as
8  * published by the Free Software Foundation.
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 "bayou.h"
21
22 struct bayoucfg bayoucfg;
23
24 static int add_payload(struct LAR *lar, struct larent *larent)
25 {
26         struct payload *payload;
27         int plen;
28         u8 *params = NULL;
29         u8 *fptr;
30
31         if (bayoucfg.n_entries == BAYOU_MAX_ENTRIES)
32                 return -1;
33
34         payload = &bayoucfg.entries[bayoucfg.n_entries];
35
36         if (strncmp((char *)larent->name, "payload/", 8))
37                 return -1;
38
39         if (larstat(lar, (const char *)larent->name, &payload->stat))
40                 return -1;
41
42         /* Make sure the LAR entry is valid. */
43         if (!lfverify(lar, (const char *)larent->name))
44                 return -1;
45
46         /* Get a pointer to the start of the file. */
47         fptr = larfptr(lar, (const char *)larent->name);
48
49         if (fptr == NULL)
50                 return -1;
51
52         if (!verify_self(fptr))
53                 return -1;
54
55         payload->pentry.index = bayoucfg.n_entries;
56         payload->pentry.parent = 0;
57         payload->pentry.type = BPT_TYPE_CHOOSER;
58         payload->pentry.flags = 0;
59
60         plen = self_get_params(fptr, &params);
61         payload_parse_params(payload, params, plen);
62
63         payload->fptr = fptr;
64
65         bayoucfg.n_entries++;
66
67         return 0;
68 }
69
70 static int lar_walk_files(struct LAR *lar,
71                           int (*cb) (struct LAR *, struct larent *))
72 {
73         struct larent *larent;
74         int ret = 0;
75
76         rewindlar(lar);
77
78         while ((larent = readlar(lar)) != NULL) {
79                 if ((ret = cb(lar, larent)))
80                         break;
81         }
82
83         return ret;
84 }
85
86 /**
87  * If reading the bayou_payload_table fails for some reason, then construct
88  * a dummy table. All valid payloads in the lar are added as chooser items.
89  */
90 static void build_dummy_table(struct LAR *lar)
91 {
92         bayoucfg.timeout = 0xFF;
93         bayoucfg.n_entries = 0;
94
95         lar_walk_files(lar, add_payload);
96 }
97
98 int get_configuration(struct LAR *lar)
99 {
100         struct larstat stat;
101         struct bpt_config *bptcfg;
102         u8 *fptr, *ptr;
103         int i;
104
105         /*
106          * If bayou_payload_table doesn't exist, then dummy up
107          * a table from the LAR contents.
108          */
109         if (larstat(lar, "bayou_payload_table", &stat) ||
110             !lfverify(lar, "bayou_payload_table"))
111                 build_dummy_table(lar);
112
113         /* Open up the BPT and get the creamy goodness within. */
114
115         fptr = larfptr(lar, "bayou_payload_table");
116
117         if (fptr == NULL)
118                 build_dummy_table(lar);
119
120         bptcfg = (struct bpt_config *)fptr;
121         bayoucfg.timeout = bptcfg->timeout;
122
123         bayoucfg.n_entries = bptcfg->entries;
124
125         if (bayoucfg.n_entries > BAYOU_MAX_ENTRIES) {
126                 printf("W:  Limiting the number of entries to %d\n",
127                        BAYOU_MAX_ENTRIES);
128                 bayoucfg.n_entries = BAYOU_MAX_ENTRIES;
129         }
130
131         ptr = fptr + sizeof(struct bpt_config);
132
133         for (i = 0; i < bayoucfg.n_entries; i++) {
134                 struct bpt_pentry *entry = (struct bpt_pentry *)ptr;
135                 struct payload *p = &(bayoucfg.entries[i]);
136                 int plen;
137                 u8 *params = NULL;
138
139                 memcpy(&p->pentry, entry, sizeof(struct bpt_pentry));
140
141                 if (entry->type != BPT_TYPE_CHAIN) {
142                         char *lname = (char *)ptr + sizeof(struct bpt_pentry);
143
144                         if (larstat(lar, (const char *)lname, &p->stat))
145                                 build_dummy_table(lar);
146
147                         if (!lfverify(lar, (const char *)lname))
148                                 build_dummy_table(lar);
149
150                         fptr = larfptr(lar, (const char *)lname);
151
152                         if (verify_self(fptr))
153                                 p->fptr = fptr;
154                         else
155                                 build_dummy_table(lar);
156
157                         plen = self_get_params(fptr, &params);
158                         payload_parse_params(p, params, plen);
159                 }
160
161                 ptr += sizeof(struct bpt_pentry) + entry->nlen;
162         }
163
164         return 0;
165 }