Home | History | Annotate | Line # | Download | only in efi
      1  1.1  christos /* $NetBSD: devpath.c,v 1.1 2025/02/24 13:47:56 christos Exp $ */
      2  1.1  christos 
      3  1.1  christos /*
      4  1.1  christos  * Redistribution and use in source and binary forms, with or without
      5  1.1  christos  * modification, are permitted provided that the following conditions
      6  1.1  christos  * are met:
      7  1.1  christos  * 1. Redistributions of source code must retain the above copyright
      8  1.1  christos  *    notice, this list of conditions and the following disclaimer.
      9  1.1  christos  * 2. Redistributions in binary form must reproduce the above copyright
     10  1.1  christos  *    notice, this list of conditions and the following disclaimer in the
     11  1.1  christos  *    documentation and/or other materials provided with the distribution.
     12  1.1  christos  *
     13  1.1  christos  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
     14  1.1  christos  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     15  1.1  christos  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     16  1.1  christos  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     17  1.1  christos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     18  1.1  christos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     19  1.1  christos  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     20  1.1  christos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     21  1.1  christos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     22  1.1  christos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     23  1.1  christos  * SUCH DAMAGE.
     24  1.1  christos  */
     25  1.1  christos 
     26  1.1  christos #include <sys/cdefs.h>
     27  1.1  christos #ifndef lint
     28  1.1  christos __RCSID("$NetBSD: devpath.c,v 1.1 2025/02/24 13:47:56 christos Exp $");
     29  1.1  christos #endif /* not lint */
     30  1.1  christos 
     31  1.1  christos #include <sys/queue.h>
     32  1.1  christos 
     33  1.1  christos #include <err.h>
     34  1.1  christos #include <assert.h>
     35  1.1  christos #include <stdio.h>
     36  1.1  christos #include <stdlib.h>
     37  1.1  christos #include <string.h>
     38  1.1  christos #include <util.h>
     39  1.1  christos 
     40  1.1  christos #include "defs.h"
     41  1.1  christos #include "devpath.h"
     42  1.1  christos #include "devpath1.h"
     43  1.1  christos #include "devpath2.h"
     44  1.1  christos #include "devpath3.h"
     45  1.1  christos #include "devpath4.h"
     46  1.1  christos #include "devpath5.h"
     47  1.1  christos 
     48  1.1  christos #define easprintf	(size_t)easprintf
     49  1.1  christos 
     50  1.1  christos typedef SIMPLEQ_HEAD(devpath_head, devpath_blk) devpath_head_t;
     51  1.1  christos 
     52  1.1  christos typedef struct devpath_blk {
     53  1.1  christos 	devpath_elm_t	path;
     54  1.1  christos 	devpath_elm_t	dbg;
     55  1.1  christos 	SIMPLEQ_ENTRY(devpath_blk) entry;
     56  1.1  christos } devpath_blk_t;
     57  1.1  christos 
     58  1.1  christos static void
     59  1.1  christos devpath_end(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
     60  1.1  christos {
     61  1.1  christos 
     62  1.1  christos 	assert(dp->Type == 0x7f);
     63  1.1  christos 	assert(dp->Length == 4);
     64  1.1  christos 
     65  1.1  christos 	switch (dp->SubType) {
     66  1.1  christos 	case 1:
     67  1.1  christos 		path->cp = estrdup("");	/* end of devpath instance */
     68  1.1  christos 		path->sz = 1;
     69  1.1  christos 		break;
     70  1.1  christos 	case 0xff:
     71  1.1  christos 		path->cp = NULL;	/* end of entire devpath */
     72  1.1  christos 		path->sz = 0;
     73  1.1  christos 		break;
     74  1.1  christos 	default:
     75  1.1  christos 		path->sz = easprintf(&path->cp,
     76  1.1  christos 		    "unknown device path end subtype: %u\n", dp->SubType);
     77  1.1  christos 		break;
     78  1.1  christos 	}
     79  1.1  christos 
     80  1.1  christos 	if (dbg != NULL)
     81  1.1  christos 		devpath_hdr(dp, dbg);
     82  1.1  christos }
     83  1.1  christos 
     84  1.1  christos static char *
     85  1.1  christos collapse_list(devpath_head_t *head, size_t plen, char **dmsg, size_t dlen)
     86  1.1  christos {
     87  1.1  christos 	devpath_blk_t *blk, *next;
     88  1.1  christos 	char *bp, *path;
     89  1.1  christos 
     90  1.1  christos 	bp = path = emalloc(plen + 1);
     91  1.1  christos 	SIMPLEQ_FOREACH_SAFE(blk, head, entry, next) {
     92  1.1  christos 		if (blk->path.cp == NULL) {
     93  1.1  christos 			*bp = '\0';
     94  1.1  christos 			assert(next == NULL);
     95  1.1  christos 			break;
     96  1.1  christos 		}
     97  1.1  christos 		else if (*blk->path.cp == '\0') {
     98  1.1  christos 			*bp++ = ':';
     99  1.1  christos 			next = SIMPLEQ_NEXT(blk, entry);
    100  1.1  christos 		}
    101  1.1  christos 		else {
    102  1.1  christos 			bp = stpcpy(bp, blk->path.cp);
    103  1.1  christos 			if (next->path.cp != NULL && *next->path.cp != '\0')
    104  1.1  christos 				*bp++ = '/';
    105  1.1  christos 		}
    106  1.1  christos 		free(blk->path.cp);
    107  1.1  christos 	}
    108  1.1  christos 	if (dmsg) {
    109  1.1  christos 		bp = *dmsg = emalloc(dlen + 1);
    110  1.1  christos 		SIMPLEQ_FOREACH_SAFE(blk, head, entry, next) {
    111  1.1  christos 			bp = stpcpy(bp, blk->dbg.cp);
    112  1.1  christos 			free(blk->dbg.cp);
    113  1.1  christos 		}
    114  1.1  christos 	}
    115  1.1  christos 	return path;
    116  1.1  christos }
    117  1.1  christos 
    118  1.1  christos static void
    119  1.1  christos devpath_parse_core(devpath_t *dp, devpath_elm_t *path, devpath_elm_t *dbg)
    120  1.1  christos {
    121  1.1  christos 
    122  1.1  christos 	switch (dp->Type) {
    123  1.1  christos 	case DEVPATH_TYPE_HW:	 devpath_hw(dp, path, dbg);	return; /* Type 1 */
    124  1.1  christos 	case DEVPATH_TYPE_ACPI:	 devpath_acpi(dp, path, dbg);	return; /* Type 2 */
    125  1.1  christos 	case DEVPATH_TYPE_MSG:	 devpath_msg(dp, path, dbg);	return; /* Type 3 */
    126  1.1  christos 	case DEVPATH_TYPE_MEDIA: devpath_media(dp, path, dbg);	return; /* Type 4 */
    127  1.1  christos 	case DEVPATH_TYPE_BIOS:	 devpath_bios(dp, path, dbg);	return; /* Type 5 */
    128  1.1  christos 	case DEVPATH_TYPE_END:	 devpath_end(dp, path, dbg);	return; /* Type 0x7F */
    129  1.1  christos 	default:		 devpath_unsupported(dp, path, dbg);	return;
    130  1.1  christos 	}
    131  1.1  christos }
    132  1.1  christos 
    133  1.1  christos PUBLIC char *
    134  1.1  christos devpath_parse(devpath_t *dp, size_t dplen, char **dmsg)
    135  1.1  christos {
    136  1.1  christos 	devpath_head_t head = SIMPLEQ_HEAD_INITIALIZER(head);
    137  1.1  christos 	devpath_blk_t *blk;
    138  1.1  christos 	union {
    139  1.1  christos 		char *cp;
    140  1.1  christos 		devpath_t *dp;
    141  1.1  christos 	} u;
    142  1.1  christos 	size_t dlen = 0, plen = 0;
    143  1.1  christos 	char *ep;
    144  1.1  christos 
    145  1.1  christos 	if (dmsg)
    146  1.1  christos 		*dmsg = NULL;
    147  1.1  christos 
    148  1.1  christos 	u.dp = dp;
    149  1.1  christos 	ep = u.cp + dplen;
    150  1.1  christos 	for (/*EMPTY*/; u.cp < ep; u.cp += u.dp->Length) {
    151  1.1  christos 		blk = ecalloc(1, sizeof(*blk));
    152  1.1  christos 		devpath_parse_core(u.dp, &blk->path, dmsg ? &blk->dbg : NULL);
    153  1.1  christos 		plen += blk->path.sz;
    154  1.1  christos 		dlen += blk->dbg.sz;
    155  1.1  christos 		SIMPLEQ_INSERT_TAIL(&head, blk, entry);
    156  1.1  christos 	}
    157  1.1  christos 
    158  1.1  christos 	return collapse_list(&head, plen, dmsg, dlen);
    159  1.1  christos }
    160