xref: /netbsd/usr.sbin/btattach/firmload.c (revision e2e1887f)
1 /* $NetBSD: firmload.c,v 1.1 2017/08/10 20:43:12 jmcneill Exp $ */
2 
3 /*-
4  * Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/param.h>
30 #include <sys/sysctl.h>
31 #include <fcntl.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 
36 #include "firmload.h"
37 
38 #define HW_FIRMWARE_PATH	"hw.firmware.path"
39 #define	HW_FIRMWARE_PATH_DELIM	":"
40 
41 static int
firmware_search(char * paths,const char * drvname,const char * imgname)42 firmware_search(char *paths, const char *drvname, const char *imgname)
43 {
44 	char *p, *f;
45 	const int debug = getenv("FIRMWARE_DEBUG") != NULL;
46 	int fd;
47 
48 	p = strtok(paths, HW_FIRMWARE_PATH_DELIM);
49 	while (p) {
50 		if (asprintf(&f, "%s/%s/%s", p, drvname, imgname) == -1)
51 			return -1;
52 		if (debug)
53 			printf("%s: trying %s...\n", __func__, f);
54 		fd = open(f, O_RDONLY);
55 		free(f);
56 		if (fd != -1) {
57 			if (debug)
58 				printf("%s: using image at %s\n", __func__, f);
59 			return fd;
60 		}
61 		p = strtok(NULL, HW_FIRMWARE_PATH_DELIM);
62 	}
63 
64 	/* Not found */
65 	return -1;
66 }
67 
68 int
firmware_open(const char * drvname,const char * imgname)69 firmware_open(const char *drvname, const char *imgname)
70 {
71 	size_t len;
72 	char *paths;
73 	int fd;
74 
75 	paths = asysctlbyname(HW_FIRMWARE_PATH, &len);
76 	if (paths == NULL)
77 		return -1;
78 
79 	fd = firmware_search(paths, drvname, imgname);
80 
81 	free(paths);
82 
83 	return fd;
84 }
85