]> git.ozlabs.org Git - petitboot/blob - ui/common/ui-system.c
ui: callback & boot actions: kexec -> boot
[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  * pb_start_daemon - start the pb-discover daemon.
37  */
38
39 int pb_start_daemon(void)
40 {
41         int result;
42         const char *argv[2];
43         char *name = talloc_asprintf(NULL, "%s/sbin/pb-discover",
44                 pb_system_apps.prefix);
45
46         argv[0] = name;
47         argv[1] =  NULL;
48
49         result = pb_run_cmd(argv, 0, 0);
50
51         talloc_free(name);
52
53         if (result)
54                 pb_log("%s: failed: (%d)\n", __func__, result);
55
56         return result;
57 }
58
59 /**
60  * kexec_load - kexec load helper.
61  * @l_image: The local image file for kexec to execute.
62  * @l_initrd: Optional local initrd file for kexec --initrd, can be NULL.
63  * @args: Optional command line args for kexec --append, can be NULL.
64  */
65
66 static int kexec_load(const char *l_image, const char *l_initrd,
67         const char *args, int dry_run)
68 {
69         int result;
70         const char *argv[6];
71         const char **p;
72         char *s_initrd = NULL;
73         char *s_args = NULL;
74
75         p = argv;
76         *p++ = pb_system_apps.kexec;    /* 1 */
77         *p++ = "-l";                    /* 2 */
78
79         if (l_initrd) {
80                 s_initrd = talloc_asprintf(NULL, "--initrd=%s", l_initrd);
81                 assert(s_initrd);
82                 *p++ = s_initrd;         /* 3 */
83         }
84
85         if (args) {
86                 s_args = talloc_asprintf(NULL, "--append=%s", args);
87                 assert(s_args);
88                 *p++ = s_args;          /* 4 */
89         }
90
91         *p++ = l_image;                 /* 5 */
92         *p++ = NULL;                    /* 6 */
93
94         result = pb_run_cmd(argv, 1, dry_run);
95
96         if (result)
97                 pb_log("%s: failed: (%d)\n", __func__, result);
98
99         talloc_free(s_initrd);
100         talloc_free(s_args);
101
102         return result;
103 }
104
105 /**
106  * kexec_reboot - Helper to boot the new kernel.
107  *
108  * Must only be called after a successful call to kexec_load().
109  */
110
111 static int kexec_reboot(int dry_run)
112 {
113         int result = 0;
114         const char *argv[4];
115         const char **p;
116
117         /* First try running shutdown.  Init scripts should run 'exec -e' */
118
119         p = argv;
120         *p++ = pb_system_apps.shutdown; /* 1 */
121         *p++ =  "-r";                   /* 2 */
122         *p++ =  "now";                  /* 3 */
123         *p++ =  NULL;                   /* 4 */
124
125         result = pb_run_cmd(argv, 1, dry_run);
126
127         /* On error, force a kexec with the -e option */
128
129         if (result) {
130                 p = argv;
131                 *p++ = pb_system_apps.kexec;    /* 1 */
132                 *p++ = "-e";                    /* 2 */
133                 *p++ = NULL;                    /* 3 */
134
135                 result = pb_run_cmd(argv, 1, 0);
136         }
137
138         if (result)
139                 pb_log("%s: failed: (%d)\n", __func__, result);
140
141         return result;
142 }
143
144 /**
145  * pb_boot - Run kexec with the supplied boot options.
146  */
147
148 int pb_boot(const struct pb_boot_data *bd, int dry_run)
149 {
150         int result;
151         char *l_image = NULL;
152         char *l_initrd = NULL;
153         unsigned int clean_image = 0;
154         unsigned int clean_initrd = 0;
155
156         pb_log("%s: image:   '%s'\n", __func__, bd->image);
157         pb_log("%s: initrd:  '%s'\n", __func__, bd->initrd);
158         pb_log("%s: args:    '%s'\n", __func__, bd->args);
159
160         result = -1;
161
162         if (bd->image) {
163                 l_image = pb_load_file(NULL, bd->image, &clean_image);
164                 if (!l_image)
165                         goto no_load;
166         }
167
168         if (bd->initrd) {
169                 l_initrd = pb_load_file(NULL, bd->initrd, &clean_initrd);
170                 if (!l_initrd)
171                         goto no_load;
172         }
173
174         if (!l_image && !l_initrd)
175                 goto no_load;
176
177         result = kexec_load(l_image, l_initrd, bd->args, dry_run);
178
179 no_load:
180         if (clean_image)
181                 unlink(l_image);
182         if (clean_initrd)
183                 unlink(l_initrd);
184
185         talloc_free(l_image);
186         talloc_free(l_initrd);
187
188         if (!result)
189                 result = kexec_reboot(dry_run);
190
191         return result;
192 }
193
194 /**
195  * pb_elf_hash - Standard elf hash routine.
196  */
197
198 unsigned int pb_elf_hash(const char *str)
199 {
200         unsigned int h = 0, g;
201
202         while (*str) {
203                 h = (h << 4) + *str++;
204                 g = h & 0xf0000000;
205                 if (g)
206                         h ^= g >> 24;
207                 h &= ~g;
208         }
209         pb_log("%s: %x\n", __func__, h);
210         return h;
211 }
212
213 /**
214  * pb_cat_hash - Hashes concatenation of two strings.
215  */
216
217 unsigned int pb_cat_hash(const char *a, const char *b)
218 {
219         unsigned int h;
220         char *s;
221
222         s = talloc_asprintf(NULL, "%s%s", a, b);
223         h = pb_elf_hash(s);
224         talloc_free(s);
225
226         return h;
227 }