/*- * Copyright 2022 John-Mark Gurney. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include #include #include #include SET_DECLARE(sysinit_set, struct sysinit); void __attribute__ ((constructor)) sysinit_run(void) { const int cnt = SET_COUNT(sysinit_set); uint16_t *idxarray = alloca(sizeof(uint16_t) * cnt); #if defined(VERBOSE_SYSINIT) uint16_t last; bool verbose; #endif int i; for (i = 0; i < cnt; i++) idxarray[i] = i; /* * following mostly copied from FreeBSD sys/kern/init_main.c * which has license: * SPDX-License-Identifier: BSD-4-Clause * * Copyright (c) 1995 Terrence R. Lambert * All rights reserved. * * Copyright (c) 1982, 1986, 1989, 1991, 1992, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * * as copying this to RAM might be expensive, use a stack * allocated indirection array to do the sorting instead. */ uint16_t *sipp; uint16_t *xipp; uint16_t save; /* * Perform a bubble sort of the system initialization objects by * their subsystem (primary key) and order (secondary key). */ #define GI(x) (SET_BEGIN(sysinit_set)[(x)]) #define GI_SUBSYSORDER(x) (GI((x))->si_subsys_order) #define GI_SUBSYS(x) (GET_SUBSYS(GI_SUBSYSORDER(x))) #define GI_ORDER(x) (GET_ORDER(GI_SUBSYSORDER(x))) for (sipp = &idxarray[0]; sipp < &idxarray[cnt]; sipp++) { for (xipp = sipp + 1; xipp < &idxarray[cnt]; xipp++) { if (GI_SUBSYS(*sipp) < GI_SUBSYS(*xipp) || (GI_SUBSYS(*sipp) == GI_SUBSYS(*xipp) && GI_ORDER(*sipp) <= GI_ORDER(*xipp))) continue; /* skip*/ save = *sipp; *sipp = *xipp; *xipp = save; } } #if defined(VERBOSE_SYSINIT) last = SI_SUB_COPYRIGHT; verbose = 0; #endif /* * Traverse the (now) ordered list of system initialization tasks. * Perform each task, and continue on to the next task. */ for (sipp = &idxarray[0]; sipp < &idxarray[cnt]; sipp++) { if (GI_SUBSYS(*sipp) == SI_SUB_DUMMY) continue; /* skip dummy task(s)*/ #if defined(VERBOSE_SYSINIT) if (GI_SUBSYS(*sipp) > last && verbose_sysinit != 0) { verbose = 1; last = GI_SUBSYS(*sipp); printf("subsystem %x\n", last); } if (verbose) { printf(" %p(%p)... ", GI(*sipp)->func, GI(*sipp)->udata); } #endif /* Call function */ (GI(*sipp)->si_func)(GI(*sipp)->si_udata); #if defined(VERBOSE_SYSINIT) if (verbose) printf("done.\n"); #endif } }