blob: b598274edc0925526708c36eabd518d5aab30ce2 [file] [log] [blame]
Kevin O'Connor59d6ca52012-05-31 00:20:55 -04001// Access to pseudo "file" interface for configuration information.
2//
3// Copyright (C) 2012 Kevin O'Connor <kevin@koconnor.net>
4//
5// This file may be distributed under the terms of the GNU LGPLv3 license.
6
7#include "config.h" // CONFIG_*
Kevin O'Connor9dea5902013-09-14 20:23:54 -04008#include "malloc.h" // free
Kevin O'Connor2d2fa312013-09-14 21:55:26 -04009#include "output.h" // dprintf
Kevin O'Connor41639f82013-09-14 19:37:36 -040010#include "romfile.h" // struct romfile_s
Kevin O'Connorfa9c66a2013-09-14 19:10:40 -040011#include "string.h" // memcmp
Kevin O'Connor59d6ca52012-05-31 00:20:55 -040012
Kevin O'Connor70c94dd2013-03-08 19:39:49 -050013static struct romfile_s *RomfileRoot VARVERIFY32INIT;
Kevin O'Connor59d6ca52012-05-31 00:20:55 -040014
15void
16romfile_add(struct romfile_s *file)
17{
Kevin O'Connorc40e3fa2013-02-09 14:55:30 -050018 dprintf(3, "Add romfile: %s (size=%d)\n", file->name, file->size);
Kevin O'Connor59d6ca52012-05-31 00:20:55 -040019 file->next = RomfileRoot;
20 RomfileRoot = file;
21}
22
23// Search for the specified file.
24static struct romfile_s *
25__romfile_findprefix(const char *prefix, int prefixlen, struct romfile_s *prev)
26{
27 struct romfile_s *cur = RomfileRoot;
28 if (prev)
29 cur = prev->next;
30 while (cur) {
31 if (memcmp(prefix, cur->name, prefixlen) == 0)
32 return cur;
33 cur = cur->next;
34 }
35 return NULL;
36}
37
38struct romfile_s *
39romfile_findprefix(const char *prefix, struct romfile_s *prev)
40{
41 return __romfile_findprefix(prefix, strlen(prefix), prev);
42}
43
44struct romfile_s *
45romfile_find(const char *name)
46{
47 return __romfile_findprefix(name, strlen(name) + 1, NULL);
48}
49
50// Helper function to find, malloc_tmphigh, and copy a romfile. This
51// function adds a trailing zero to the malloc'd copy.
52void *
53romfile_loadfile(const char *name, int *psize)
54{
55 struct romfile_s *file = romfile_find(name);
56 if (!file)
57 return NULL;
58
59 int filesize = file->size;
60 if (!filesize)
61 return NULL;
62
63 char *data = malloc_tmphigh(filesize+1);
64 if (!data) {
65 warn_noalloc();
66 return NULL;
67 }
68
69 dprintf(5, "Copying romfile '%s' (len %d)\n", name, filesize);
70 int ret = file->copy(file, data, filesize);
71 if (ret < 0) {
72 free(data);
73 return NULL;
74 }
75 if (psize)
76 *psize = filesize;
77 data[filesize] = '\0';
78 return data;
79}
80
81// Attempt to load an integer from the given file - return 'defval'
Kevin O'Connor296ce222014-01-15 13:33:48 -050082// if unsuccessful.
Kevin O'Connor59d6ca52012-05-31 00:20:55 -040083u64
84romfile_loadint(const char *name, u64 defval)
85{
86 struct romfile_s *file = romfile_find(name);
87 if (!file)
88 return defval;
89
90 int filesize = file->size;
91 if (!filesize || filesize > sizeof(u64) || (filesize & (filesize-1)))
92 // Doesn't look like a valid integer.
93 return defval;
94
95 u64 val = 0;
96 int ret = file->copy(file, &val, sizeof(val));
97 if (ret < 0)
98 return defval;
99 return val;
100}
Gerd Hoffmann1bda7242017-09-18 10:47:21 +0200101
102struct const_romfile_s {
103 struct romfile_s file;
104 void *data;
105};
106
107static int
108const_read_file(struct romfile_s *file, void *dst, u32 maxlen)
109{
110 if (file->size > maxlen)
111 return -1;
112 struct const_romfile_s *cfile;
113 cfile = container_of(file, struct const_romfile_s, file);
114 if (maxlen > file->size)
115 maxlen = file->size;
116 memcpy(dst, cfile->data, maxlen);
117 return file->size;
118}
119
120static void
121const_romfile_add(char *name, void *data, int size)
122{
123 struct const_romfile_s *cfile = malloc_tmp(sizeof(*cfile));
124 if (!cfile) {
125 warn_noalloc();
126 return;
127 }
128 memset(cfile, 0, sizeof(*cfile));
129 strtcpy(cfile->file.name, name, sizeof(cfile->file.name));
130 cfile->file.size = size;
131 cfile->file.copy = const_read_file;
132 cfile->data = data;
133 romfile_add(&cfile->file);
134}
135
136void
137const_romfile_add_int(char *name, u32 value)
138{
139 u32 *data = malloc_tmp(sizeof(*data));
140 if (!data) {
141 warn_noalloc();
142 return;
143 }
144 *data = value;
145 const_romfile_add(name, data, sizeof(*data));
146}