• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (C) 2009 The Android Open Source Project
2 **
3 ** This software is licensed under the terms of the GNU General Public
4 ** License version 2, as published by the Free Software Foundation, and
5 ** may be copied, distributed, and modified under those terms.
6 **
7 ** This program is distributed in the hope that it will be useful,
8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 ** GNU General Public License for more details.
11 */
12 
13 #include "android/boot-properties.h"
14 #include "android/utils/debug.h"
15 #include "android/utils/system.h"
16 #include "android/hw-qemud.h"
17 #include "android/globals.h"
18 
19 #define  D(...)  VERBOSE_PRINT(init,__VA_ARGS__)
20 
21 /* define T_ACTIVE to 1 to debug transport communications */
22 #define  T_ACTIVE  0
23 
24 #if T_ACTIVE
25 #define  T(...)  VERBOSE_PRINT(init,__VA_ARGS__)
26 #else
27 #define  T(...)   ((void)0)
28 #endif
29 
30 /* this code supports the list of system properties that will
31  * be set on boot in the emulated system.
32  */
33 
34 typedef struct BootProperty {
35     struct BootProperty*  next;
36     char*                 property;
37     int                   length;
38 } BootProperty;
39 
40 static BootProperty*
boot_property_alloc(const char * name,int namelen,const char * value,int valuelen)41 boot_property_alloc( const char*  name,  int  namelen,
42                      const char*  value, int  valuelen )
43 {
44     int            length = namelen + 1 + valuelen;
45     BootProperty*  prop = android_alloc( sizeof(*prop) + length + 1 );
46     char*          p;
47 
48     prop->next     = NULL;
49     prop->property = p = (char*)(prop + 1);
50     prop->length   = length;
51 
52     memcpy( p, name, namelen );
53     p += namelen;
54     *p++ = '=';
55     memcpy( p, value, valuelen );
56     p += valuelen;
57     *p = '\0';
58 
59     return prop;
60 }
61 
62 static BootProperty*   _boot_properties;
63 static BootProperty**  _boot_properties_tail = &_boot_properties;
64 static int             _inited;
65 
66 int
boot_property_add2(const char * name,int namelen,const char * value,int valuelen)67 boot_property_add2( const char*  name, int  namelen,
68                     const char*  value, int  valuelen )
69 {
70     BootProperty*  prop;
71 
72     /* check the lengths
73      */
74     if (namelen > PROPERTY_MAX_NAME)
75         return -1;
76 
77     if (valuelen > PROPERTY_MAX_VALUE)
78         return -2;
79 
80     /* check that there are not invalid characters in the
81      * property name
82      */
83     const char*  reject = " =$*?'\"";
84     int          nn;
85 
86     for (nn = 0; nn < namelen; nn++) {
87         if (strchr(reject, name[nn]) != NULL)
88             return -3;
89     }
90 
91     /* init service if needed */
92     if (!_inited) {
93         boot_property_init_service();
94         _inited = 1;
95     }
96 
97     D("Adding boot property: '%.*s' = '%.*s'",
98       namelen, name, valuelen, value);
99 
100     /* add to the internal list */
101     prop = boot_property_alloc(name, namelen, value, valuelen);
102 
103     *_boot_properties_tail = prop;
104     _boot_properties_tail  = &prop->next;
105 
106     return 0;
107 }
108 
109 
110 int
boot_property_add(const char * name,const char * value)111 boot_property_add( const char*  name, const char*  value )
112 {
113     int  namelen = strlen(name);
114     int  valuelen = strlen(value);
115 
116     return boot_property_add2(name, namelen, value, valuelen);
117 }
118 
119 
120 
121 #define SERVICE_NAME  "boot-properties"
122 
123 static void
boot_property_client_recv(void * opaque,uint8_t * msg,int msglen,QemudClient * client)124 boot_property_client_recv( void*         opaque,
125                            uint8_t*      msg,
126                            int           msglen,
127                            QemudClient*  client )
128 {
129     /* the 'list' command shall send all boot properties
130      * to the client, then close the connection.
131      */
132     if (msglen == 4 && !memcmp(msg, "list", 4)) {
133         BootProperty*  prop;
134         for (prop = _boot_properties; prop != NULL; prop = prop->next) {
135             qemud_client_send(client, (uint8_t*)prop->property, prop->length);
136         }
137 
138         /* Send a NUL to signal the end of the list. */
139         qemud_client_send(client, (uint8_t*)"", 1);
140 
141         qemud_client_close(client);
142         return;
143     }
144 
145     /* unknown command ? */
146     D("%s: ignoring unknown command: %.*s", __FUNCTION__, msglen, msg);
147 }
148 
149 static QemudClient*
boot_property_service_connect(void * opaque,QemudService * serv,int channel)150 boot_property_service_connect( void*          opaque,
151                                QemudService*  serv,
152                                int            channel )
153 {
154     QemudClient*  client;
155 
156     client = qemud_client_new( serv, channel, NULL,
157                                boot_property_client_recv,
158                                NULL );
159 
160     qemud_client_set_framing(client, 1);
161     return client;
162 }
163 
164 
165 void
boot_property_init_service(void)166 boot_property_init_service( void )
167 {
168     if (!_inited) {
169         QemudService*  serv = qemud_service_register( SERVICE_NAME,
170                                                     1, NULL,
171                                                     boot_property_service_connect );
172         if (serv == NULL) {
173             derror("could not register '%s' service", SERVICE_NAME);
174             return;
175         }
176         D("registered '%s' qemud service", SERVICE_NAME);
177     }
178 }
179 
180 
181 
182 void
boot_property_parse_option(const char * param)183 boot_property_parse_option( const char*  param )
184 {
185     char* q = strchr(param,'=');
186     const char* name;
187     const char* value;
188     int   namelen, valuelen, ret;
189 
190     if (q == NULL) {
191         dwarning("boot property missing (=) separator: %s", param);
192         return;
193     }
194 
195     name    = param;
196     namelen = q - param;
197 
198     value    = q+1;
199     valuelen = strlen(name) - (namelen+1);
200 
201     ret = boot_property_add2(name, namelen, value, valuelen);
202     if (ret < 0) {
203         switch (ret) {
204         case -1:
205             dwarning("boot property name too long: '%.*s'",
206                         namelen, name);
207             break;
208         case -2:
209             dwarning("boot property value too long: '%.*s'",
210                         valuelen, value);
211             break;
212         case -3:
213             dwarning("boot property name contains invalid chars: %.*s",
214                         namelen, name);
215             break;
216         }
217     }
218 }
219