• 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         qemud_client_close(client);
138         return;
139     }
140 
141     /* unknown command ? */
142     D("%s: ignoring unknown command: %.*s", __FUNCTION__, msglen, msg);
143 }
144 
145 static QemudClient*
boot_property_service_connect(void * opaque,QemudService * serv,int channel)146 boot_property_service_connect( void*          opaque,
147                                QemudService*  serv,
148                                int            channel )
149 {
150     QemudClient*  client;
151 
152     client = qemud_client_new( serv, channel, NULL,
153                                boot_property_client_recv,
154                                NULL );
155 
156     qemud_client_set_framing(client, 1);
157     return client;
158 }
159 
160 
161 void
boot_property_init_service(void)162 boot_property_init_service( void )
163 {
164     if (!_inited) {
165         QemudService*  serv = qemud_service_register( SERVICE_NAME,
166                                                     1, NULL,
167                                                     boot_property_service_connect );
168         if (serv == NULL) {
169             derror("could not register '%s' service", SERVICE_NAME);
170             return;
171         }
172         D("registered '%s' qemud service", SERVICE_NAME);
173     }
174 }
175 
176 
177 
178 void
boot_property_parse_option(const char * param)179 boot_property_parse_option( const char*  param )
180 {
181     char* q = strchr(param,'=');
182     const char* name;
183     const char* value;
184     int   namelen, valuelen, ret;
185 
186     if (q == NULL) {
187         dwarning("boot property missing (=) separator: %s", param);
188         return;
189     }
190 
191     name    = param;
192     namelen = q - param;
193 
194     value    = q+1;
195     valuelen = strlen(name) - (namelen+1);
196 
197     ret = boot_property_add2(name, namelen, value, valuelen);
198     if (ret < 0) {
199         switch (ret) {
200         case -1:
201             dwarning("boot property name too long: '%.*s'",
202                         namelen, name);
203             break;
204         case -2:
205             dwarning("boot property value too long: '%.*s'",
206                         valuelen, value);
207             break;
208         case -3:
209             dwarning("boot property name contains invalid chars: %.*s",
210                         namelen, name);
211             break;
212         }
213     }
214 }
215