1*af901e68Snonaka /* $NetBSD: loadfile_zboot.c,v 1.1 2009/03/02 09:33:02 nonaka Exp $ */
2*af901e68Snonaka
3*af901e68Snonaka /*
4*af901e68Snonaka * Copyright (c) 2009 NONAKA Kimihiro <nonaka@netbsd.org>
5*af901e68Snonaka * All rights reserved.
6*af901e68Snonaka *
7*af901e68Snonaka * Redistribution and use in source and binary forms, with or without
8*af901e68Snonaka * modification, are permitted provided that the following conditions
9*af901e68Snonaka * are met:
10*af901e68Snonaka * 1. Redistributions of source code must retain the above copyright
11*af901e68Snonaka * notice, this list of conditions and the following disclaimer.
12*af901e68Snonaka * 2. Redistributions in binary form must reproduce the above copyright
13*af901e68Snonaka * notice, this list of conditions and the following disclaimer in the
14*af901e68Snonaka * documentation and/or other materials provided with the distribution.
15*af901e68Snonaka *
16*af901e68Snonaka * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17*af901e68Snonaka * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18*af901e68Snonaka * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19*af901e68Snonaka * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20*af901e68Snonaka * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21*af901e68Snonaka * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22*af901e68Snonaka * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23*af901e68Snonaka * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24*af901e68Snonaka * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25*af901e68Snonaka * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*af901e68Snonaka */
27*af901e68Snonaka
28*af901e68Snonaka #include <sys/types.h>
29*af901e68Snonaka #include <sys/bootblock.h>
30*af901e68Snonaka
31*af901e68Snonaka #include "boot.h"
32*af901e68Snonaka #include "bootinfo.h"
33*af901e68Snonaka #include "disk.h"
34*af901e68Snonaka #include "unixdev.h"
35*af901e68Snonaka #include "pathnames.h"
36*af901e68Snonaka
37*af901e68Snonaka #include <lib/libsa/loadfile.h>
38*af901e68Snonaka
39*af901e68Snonaka #include "compat_linux.h"
40*af901e68Snonaka
41*af901e68Snonaka static int fdloadfile_zboot(int fd, u_long *marks, int flags);
42*af901e68Snonaka static int zboot_exec(int fd, u_long *marks, int flags);
43*af901e68Snonaka
44*af901e68Snonaka int
loadfile_zboot(const char * fname,u_long * marks,int flags)45*af901e68Snonaka loadfile_zboot(const char *fname, u_long *marks, int flags)
46*af901e68Snonaka {
47*af901e68Snonaka int fd, error;
48*af901e68Snonaka
49*af901e68Snonaka /* Open the file. */
50*af901e68Snonaka if ((fd = open(fname, 0)) < 0) {
51*af901e68Snonaka WARN(("open %s", fname ? fname : "<default>"));
52*af901e68Snonaka return -1;
53*af901e68Snonaka }
54*af901e68Snonaka
55*af901e68Snonaka /* Load it; save the value of errno across the close() call */
56*af901e68Snonaka if ((error = fdloadfile_zboot(fd, marks, flags)) != 0) {
57*af901e68Snonaka (void)close(fd);
58*af901e68Snonaka errno = error;
59*af901e68Snonaka return -1;
60*af901e68Snonaka }
61*af901e68Snonaka
62*af901e68Snonaka return fd;
63*af901e68Snonaka }
64*af901e68Snonaka
65*af901e68Snonaka static int
fdloadfile_zboot(int fd,u_long * marks,int flags)66*af901e68Snonaka fdloadfile_zboot(int fd, u_long *marks, int flags)
67*af901e68Snonaka {
68*af901e68Snonaka Elf32_Ehdr elf32;
69*af901e68Snonaka ssize_t nr;
70*af901e68Snonaka int rval;
71*af901e68Snonaka
72*af901e68Snonaka /* Read the exec header. */
73*af901e68Snonaka if (lseek(fd, 0, SEEK_SET) == (off_t)-1)
74*af901e68Snonaka goto err;
75*af901e68Snonaka nr = read(fd, &elf32, sizeof(elf32));
76*af901e68Snonaka if (nr == -1) {
77*af901e68Snonaka WARN(("read header failed"));
78*af901e68Snonaka goto err;
79*af901e68Snonaka }
80*af901e68Snonaka if (nr != sizeof(elf32)) {
81*af901e68Snonaka WARN(("read header short"));
82*af901e68Snonaka errno = EFTYPE;
83*af901e68Snonaka goto err;
84*af901e68Snonaka }
85*af901e68Snonaka
86*af901e68Snonaka if (memcmp(elf32.e_ident, ELFMAG, SELFMAG) == 0 &&
87*af901e68Snonaka elf32.e_ident[EI_CLASS] == ELFCLASS32) {
88*af901e68Snonaka rval = zboot_exec(fd, marks, flags);
89*af901e68Snonaka } else {
90*af901e68Snonaka rval = 1;
91*af901e68Snonaka errno = EFTYPE;
92*af901e68Snonaka }
93*af901e68Snonaka
94*af901e68Snonaka if (rval == 0)
95*af901e68Snonaka return 0;
96*af901e68Snonaka err:
97*af901e68Snonaka return errno;
98*af901e68Snonaka }
99*af901e68Snonaka
100*af901e68Snonaka static int
zboot_exec(int fd,u_long * marks,int flags)101*af901e68Snonaka zboot_exec(int fd, u_long *marks, int flags)
102*af901e68Snonaka {
103*af901e68Snonaka static char bibuf[BOOTINFO_MAXSIZE];
104*af901e68Snonaka char buf[512];
105*af901e68Snonaka struct btinfo_common *help;
106*af901e68Snonaka char *p;
107*af901e68Snonaka int tofd;
108*af901e68Snonaka int sz;
109*af901e68Snonaka int i;
110*af901e68Snonaka
111*af901e68Snonaka /*
112*af901e68Snonaka * set bootargs
113*af901e68Snonaka */
114*af901e68Snonaka p = bibuf;
115*af901e68Snonaka memcpy(p, &bootinfo->nentries, sizeof(bootinfo->nentries));
116*af901e68Snonaka p += sizeof(bootinfo->nentries);
117*af901e68Snonaka for (i = 0; i < bootinfo->nentries; i++) {
118*af901e68Snonaka help = (struct btinfo_common *)(bootinfo->entry[i]);
119*af901e68Snonaka if ((p - bibuf) + help->len > BOOTINFO_MAXSIZE)
120*af901e68Snonaka break;
121*af901e68Snonaka
122*af901e68Snonaka memcpy(p, help, help->len);
123*af901e68Snonaka p += help->len;
124*af901e68Snonaka }
125*af901e68Snonaka
126*af901e68Snonaka tofd = uopen(_PATH_ZBOOT, LINUX_O_WRONLY);
127*af901e68Snonaka if (tofd == -1) {
128*af901e68Snonaka printf("%s: can't open (errno %d)\n", _PATH_ZBOOT, errno);
129*af901e68Snonaka return 1;
130*af901e68Snonaka }
131*af901e68Snonaka
132*af901e68Snonaka if (uwrite(tofd, bibuf, p - bibuf) != p - bibuf)
133*af901e68Snonaka printf("setbootargs: argument write error\n");
134*af901e68Snonaka
135*af901e68Snonaka /* Commit boot arguments. */
136*af901e68Snonaka uclose(tofd);
137*af901e68Snonaka
138*af901e68Snonaka /*
139*af901e68Snonaka * load kernel
140*af901e68Snonaka */
141*af901e68Snonaka tofd = uopen(_PATH_ZBOOT, LINUX_O_WRONLY);
142*af901e68Snonaka if (tofd == -1) {
143*af901e68Snonaka printf("%s: can't open (errno %d)\n", _PATH_ZBOOT, errno);
144*af901e68Snonaka return 1;
145*af901e68Snonaka }
146*af901e68Snonaka
147*af901e68Snonaka if (lseek(fd, 0, SEEK_SET) != 0) {
148*af901e68Snonaka printf("%s: seek error\n", _PATH_ZBOOT);
149*af901e68Snonaka goto err;
150*af901e68Snonaka }
151*af901e68Snonaka
152*af901e68Snonaka while ((sz = read(fd, buf, sizeof(buf))) == sizeof(buf)) {
153*af901e68Snonaka if ((sz = uwrite(tofd, buf, sz)) != sizeof(buf)) {
154*af901e68Snonaka printf("%s: write error\n", _PATH_ZBOOT);
155*af901e68Snonaka goto err;
156*af901e68Snonaka }
157*af901e68Snonaka }
158*af901e68Snonaka
159*af901e68Snonaka if (sz < 0) {
160*af901e68Snonaka printf("zboot_exec: read error\n");
161*af901e68Snonaka goto err;
162*af901e68Snonaka }
163*af901e68Snonaka
164*af901e68Snonaka if (sz >= 0 && uwrite(tofd, buf, sz) != sz) {
165*af901e68Snonaka printf("zboot_exec: write error\n");
166*af901e68Snonaka goto err;
167*af901e68Snonaka }
168*af901e68Snonaka
169*af901e68Snonaka uclose(tofd);
170*af901e68Snonaka /*NOTREACHED*/
171*af901e68Snonaka return 0;
172*af901e68Snonaka
173*af901e68Snonaka err:
174*af901e68Snonaka uclose(tofd);
175*af901e68Snonaka return 1;
176*af901e68Snonaka }
177