Log file cleanups
[petitboot] / ui / common / ui-system.c
1 /*
2  *  Copyright (C) 2009 Sony Computer Entertainment Inc.
3  *  Copyright 2009 Sony Corp.
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; version 2 of the License.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19 #define _GNU_SOURCE
20
21 #include <assert.h>
22 #include <errno.h>
23 #include <signal.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/types.h>
27 #include <sys/wait.h>
28
29 #include "log/log.h"
30 #include <system/system.h>
31 #include "talloc/talloc.h"
32 #include "loader.h"
33 #include "ui-system.h"
34
35 /**
36  * kexec_load - kexec load helper.
37  * @l_image: The local image file for kexec to execute.
38  * @l_initrd: Optional local initrd file for kexec --initrd, can be NULL.
39  * @args: Optional command line args for kexec --append, can be NULL.
40  */
41
42 static int kexec_load(const char *l_image, const char *l_initrd,
43         const char *args)
44 {
45         int result;
46         const char *argv[6];
47         const char **p;
48         char *s_initrd = NULL;
49         char *s_args = NULL;
50
51         p = argv;
52         *p++ = pb_system_apps.kexec;    /* 1 */
53         *p++ = "-l";                    /* 2 */
54
55         if (l_initrd) {
56                 s_initrd = talloc_asprintf(NULL, "--initrd=%s", l_initrd);
57                 assert(s_initrd);
58                 *p++ = s_initrd;         /* 3 */
59         }
60
61         if (args) {
62                 s_args = talloc_asprintf(NULL, "--append=%s", args);
63                 assert(s_args);
64                 *p++ = s_args;          /* 4 */
65         }
66
67         *p++ = l_image;                 /* 5 */
68         *p++ = NULL;                    /* 6 */
69
70         result = pb_run_cmd(argv);
71
72         if (result)
73                 pb_log("%s: failed: (%d)\n", __func__, result);
74
75         talloc_free(s_initrd);
76         talloc_free(s_args);
77
78         return result;
79 }
80
81 /**
82  * kexec_reboot - Helper to boot the new kernel.
83  *
84  * Must only be called after a successful call to kexec_load().
85  */
86
87 static int kexec_reboot(void)
88 {
89         int result;
90         const char *argv[4];
91         const char **p;
92
93         /* First try running shutdown.  Init scripts should run 'exec -e' */
94
95         p = argv;
96         *p++ = pb_system_apps.shutdown; /* 1 */
97         *p++ =  "-r";                   /* 2 */
98         *p++ =  "now";                  /* 3 */
99         *p++ =  NULL;                   /* 4 */
100
101         result = pb_run_cmd(argv);
102
103         /* On error, force a kexec with the -e option */
104
105         if (result) {
106                 p = argv;
107                 *p++ = pb_system_apps.kexec;    /* 1 */
108                 *p++ = "-e";                    /* 2 */
109                 *p++ = NULL;                    /* 3 */
110
111                 result = pb_run_cmd(argv);
112         }
113
114         if (result)
115                 pb_log("%s: failed: (%d)\n", __func__, result);
116
117         return result;
118 }
119
120 /**
121  * pb_run_kexec - Run kexec with the supplied boot options.
122  */
123
124 int pb_run_kexec(const struct pb_kexec_data *kd)
125 {
126         int result;
127         char *l_image = NULL;
128         char *l_initrd = NULL;
129         unsigned int clean_image = 0;
130         unsigned int clean_initrd = 0;
131
132         pb_log("%s: image:  '%s'\n", __func__, kd->image);
133         pb_log("%s: initrd: '%s'\n", __func__, kd->initrd);
134         pb_log("%s: args:   '%s'\n", __func__, kd->args);
135
136         result = -1;
137
138         if (kd->image) {
139                 l_image = pb_load_file(NULL, kd->image, &clean_image);
140                 if (!l_image)
141                         goto no_load;
142         }
143
144         if (kd->initrd) {
145                 l_initrd = pb_load_file(NULL, kd->initrd, &clean_initrd);
146                 if (!l_initrd)
147                         goto no_load;
148         }
149
150         if (!l_image && !l_initrd)
151                 goto no_load;
152
153         result = kexec_load(l_image, l_initrd, kd->args);
154
155 no_load:
156         if (clean_image)
157                 unlink(l_image);
158         if (clean_initrd)
159                 unlink(l_initrd);
160
161         talloc_free(l_image);
162         talloc_free(l_initrd);
163
164         if (!result)
165                 result = kexec_reboot();
166
167         return result;
168 }
169
170 /**
171  * pb_elf_hash - Standard elf hash routine.
172  */
173
174 unsigned int pb_elf_hash(const char *str)
175 {
176         unsigned int h = 0, g;
177
178         while (*str) {
179                 h = (h << 4) + *str++;
180                 g = h & 0xf0000000;
181                 if (g)
182                         h ^= g >> 24;
183                 h &= ~g;
184         }
185         pb_log("%s: %x\n", __func__, h);
186         return h;
187 }
188
189 /**
190  * pb_cat_hash - Hashes concatenation of two strings.
191  */
192
193 unsigned int pb_cat_hash(const char *a, const char *b)
194 {
195         unsigned int h;
196         char *s;
197
198         s = talloc_asprintf(NULL, "%s%s", a, b);
199         h = pb_elf_hash(s);
200         talloc_free(s);
201
202         return h;
203 }