xref: /netbsd-src/sys/arch/zaurus/stand/zboot/loadfile_zboot.c (revision af901e6821b099f0e66f8a990b0ac16c6ab6faf9)
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