diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/include/usr/hbotcompid.H | 7 | ||||
-rw-r--r-- | src/include/usr/initservice/initsvcreasoncodes.H | 66 | ||||
-rw-r--r-- | src/makefile | 18 | ||||
-rw-r--r-- | src/sys/init/init_main.C | 61 | ||||
-rw-r--r-- | src/sys/vfs/vfs_main.C | 22 | ||||
-rw-r--r-- | src/usr/example/example.C | 7 | ||||
-rw-r--r-- | src/usr/initservice/initservice.C | 418 | ||||
-rw-r--r-- | src/usr/initservice/initservice.H | 448 | ||||
-rw-r--r-- | src/usr/initservice/initservicetaskentry.C | 67 | ||||
-rw-r--r-- | src/usr/initservice/initservicevfs1.C | 69 | ||||
-rw-r--r-- | src/usr/initservice/initservicevfs2.C | 176 | ||||
-rw-r--r-- | src/usr/initservice/initsvctasks.H | 79 | ||||
-rw-r--r-- | src/usr/initservice/makefile | 11 | ||||
-rw-r--r-- | src/usr/initservice/test/initservicetest.H | 237 | ||||
-rw-r--r-- | src/usr/initservice/test/makefile | 6 | ||||
-rw-r--r-- | src/usr/makefile | 2 |
16 files changed, 1632 insertions, 62 deletions
diff --git a/src/include/usr/hbotcompid.H b/src/include/usr/hbotcompid.H index e6be3adc8..5611fd69c 100644 --- a/src/include/usr/hbotcompid.H +++ b/src/include/usr/hbotcompid.H @@ -60,6 +60,13 @@ const char SCOM_COMP_NAME[] = "scom"; //@{ const compId_t XSCOM_COMP_ID = 0x0400; const char XSCOM_COMP_NAME[] = "xscom"; + +/** @name INITSERVICE + * Initialization Service component + */ +//@{ +const compId_t INITSVC_COMP_ID = 0x0500; +const char INITSVC_COMP_NAME[] = "initservice"; //@} #endif diff --git a/src/include/usr/initservice/initsvcreasoncodes.H b/src/include/usr/initservice/initsvcreasoncodes.H new file mode 100644 index 000000000..41b11f43d --- /dev/null +++ b/src/include/usr/initservice/initsvcreasoncodes.H @@ -0,0 +1,66 @@ +/** + * @file initsvcreasoncodes.H + * + * Detail all the possible reason codes for errorlog returns + * + */ +#ifndef __INITSERVICE_RC_H +#define __INITSERVICE_RC_H + +#include <hbotcompid.H> + +namespace INITSERVICE +{ + +/** + * @enum InitServiceModuleID + * + * module id's used in returned errorlogs + */ +enum InitServiceModuleID +{ + START_TRACE_ID = 0x00, + START_ERRL_ID, + START_XSCOMDD_ID, + START_PNORDD_ID, + START_VFS_2_ID, + START_TARGETTING_ID, + GET_MASTER_CHIP_TARGET_ID, + START_MAILBOXDD_ID, + START_SP_COMM_ID, + ENABLE_STREAMING_TRACE_ID, + START_PROGRESS_CODES_ID, + START_FSIDD_ID, + SETUP_SLAVE_LINKS_ID, + START_FSISCOM_ID, + START_FSI_II2C_ID, + START_HWP_ID, + READ_MAX_CONFIG_FROM_PNOR_ID, + APPLY_PRESENCE_DETECT_ID, + APPLY_PARTIAL_BAD_ID, + APPLY_GARD_ID, + COLLECT_HW_IDEC_ID, + VERIFY_IDEC_ID, + DISABLE_WATCHDOG_ID, + EXECUTE_ISTEPS_ID, + + // reserve some tasks for my unit tests... + INIT_SVC_TEST1_ID = 0xf0, + INIT_SVC_TEST2_ID, + INIT_SVC_TEST3_ID, + INIT_SVC_TEST4_ID, + INIT_SVC_TEST5_ID, + +}; + + +enum InitServiceReasonCode +{ + START_TASK_FAILED = INITSVC_COMP_ID | 0x01, + + +}; + +}; // namespace INITSERVICE + +#endif diff --git a/src/makefile b/src/makefile index 5411d747a..c86f33ea5 100644 --- a/src/makefile +++ b/src/makefile @@ -5,34 +5,34 @@ IMGS = hbicore hbicore_test EXTRA_LIDS = dslid BASE_OBJECTS = console.o spinlock.o string.o stdlib.o assert.o stdio.o \ - builtins.o vfs_init.o heapmgr.o pagemgr.o + builtins.o vfs_init.o heapmgr.o pagemgr.o DIRECT_BOOT_OBJECTS = start.o kernel.o taskmgr.o cpumgr.o syscall.o \ - scheduler.o exception.o vmmmgr.o timemgr.o \ - syscall_stub.o syscall_task.o \ - syscall_msg.o syscall_mmio.o syscall_time.o \ - init_main.o vfs_main.o sync.o futexmgr.o + scheduler.o exception.o vmmmgr.o timemgr.o \ + syscall_stub.o syscall_task.o \ + syscall_msg.o syscall_mmio.o syscall_time.o \ + init_main.o vfs_main.o sync.o futexmgr.o RUNTIME_OBJECTS = -BASE_MODULES = trace errl devicefw scom xscom +BASE_MODULES = trace errl devicefw scom xscom initservice EXTENDED_MODULES = targeting DIRECT_BOOT_MODULES = example RUNTIME_MODULES = TESTCASE_MODULES = cxxtest testerrl testdevicefw testsyslib \ - testscom testxscom testtargeting + testscom testxscom testtargeting testinitservice RELOCATABLE_IMAGE_LDFLAGS = -pie --export-dynamic hbicore_OBJECTS = ${BASE_OBJECTS} ${DIRECT_BOOT_OBJECTS} -hbicore_MODULES = ${BASE_MODULES} ${EXTENDED_MODULES} ${DIRECT_BOOT_MODULES} +hbicore_MODULES = ${BASE_MODULES} ${EXTENDED_MODULES} ${DIRECT_BOOT_MODULES} hbicore_LIDNUMBER = 80f00100 hbicore_test_OBJECTS = ${hbicore_OBJECTS} hbicore_test_MODULES = ${hbicore_MODULES} ${TESTCASE_MODULES} #halruntime_OBJECTS = ${BASE_OBJECTS} ${RUNTIME_OBJECTS} -#halruntime_MODULES = ${BASE_MODULES} ${EXTENDED_MODULES} ${RUNTIME_MODULES} +#halruntime_MODULES = ${BASE_MODULES} ${EXTENDED_MODULES} ${RUNTIME_MODULES} #halruntime_LDFLAGS = ${RELOCATABLE_IMAGE_LDFLAGS} #halruntime_LIDNUMBER = 80f00101 diff --git a/src/sys/init/init_main.C b/src/sys/init/init_main.C index dd83ea131..5a7cf16ae 100644 --- a/src/sys/init/init_main.C +++ b/src/sys/init/init_main.C @@ -7,62 +7,39 @@ #include <sys/sync.h> #include <sys/msg.h> #include <sys/mmio.h> +#include <assert.h> -mutex_t global_mutex = MUTEX_INITIALIZER; - -/* -void init_child(void* unused) -{ - mutex_lock(&global_mutex); - printk("Crun: %d on %d\n", task_gettid(), task_getcpuid()); - mutex_unlock(&global_mutex); - for (volatile int i = 0 ; i < 100000; i++); - task_end(); -} -*/ void vfs_main(void*); void init_main(void* unused) { - printk("Starting init!\n"); - - printk("Bringing up VFS..."); - task_create(&vfs_main, NULL); - - // TODO... add a barrier to ensure VFS is fully up. - while (NULL == _syscall0(Systemcalls::MSGQ_RESOLVE_ROOT)) - task_yield(); - + tid_t tidrc = 0; -/* - uint64_t* mmio_addr = (uint64_t*) mmio_map((void*)0x800000000, 1); - printk("MMIO Access %lx\n", *mmio_addr); + printk("Starting init!\n"); - msg_q_t msgq = msg_q_create(); - msg_q_register(msgq, "/msg/init"); + printk("Bringing up VFS..."); + task_create( &vfs_main, NULL ); - msg_t* msg = msg_allocate(); - msg->type = 1; msg->data[0] = 0xDEADBEEF12345678; - msg_send(msgq, msg); - msg = msg_wait(msgq); + // TODO... add a barrier to ensure VFS is fully up. + while (NULL == _syscall0(Systemcalls::MSGQ_RESOLVE_ROOT)) + task_yield(); - printk("Got Message: %lx\n", msg->data[0]); - while(1) + // run initialization service to start up everything else. + printk("init_main: Starting Initialization Service...\n"); + tidrc = task_exec( "libinitservice.so", NULL ); + if ( (int16_t)tidrc < 0 ) // task_exec returned a -1 { - mutex_lock(&global_mutex); - int t = task_create(&init_child, NULL); - printk("Create child %d\n", t); - for (volatile int i = 0 ; i < 1000000; i++); - mutex_unlock(&global_mutex); + printk( "ERROR: init_main: failed to launch initservice: %d\n", tidrc ); + + assert( 0 ); // stop here. } -*/ - task_exec("libexample.so", NULL); + // should never reach this point... + task_end(); + - task_exec("libcxxtest.so", NULL); - while(1) - task_yield(); + task_yield(); } diff --git a/src/sys/vfs/vfs_main.C b/src/sys/vfs/vfs_main.C index 22cd306a5..322768fc9 100644 --- a/src/sys/vfs/vfs_main.C +++ b/src/sys/vfs/vfs_main.C @@ -26,7 +26,7 @@ struct VfsEntry typedef VfsPath key_type; key_type key; msg_q_t msg_q; - + VfsEntry* next; VfsEntry* prev; }; @@ -36,10 +36,10 @@ void vfs_main(void* unused) // Create message queue, register with kernel. msg_q_t vfsMsgQ = msg_q_create(); msg_q_register(vfsMsgQ, VFS_ROOT); - + printk("done.\n"); // TODO... barrier with init. - + // Initalize modules. vfs_module_init(); @@ -73,21 +73,27 @@ void vfs_main(void* unused) msg->data[0] = (uint64_t) NULL; else msg->data[0] = (uint64_t) e->msg_q; - msg_respond(vfsMsgQ, msg); + msg_respond(vfsMsgQ, msg); } break; - + case VFS_MSG_EXEC: { - printk("VFS: Got exec request of %s\n", + printk("VFS: Got exec request of %s\n", (const char*)msg->data[0]); VfsSystemModule* module = &VFS_MODULES[0]; tid_t child = -1; while ('\0' != module->module[0]) { - if (0 == strcmp((const char*) msg->data[0], + if (0 == strcmp((const char*) msg->data[0], module->module)) { + if ( module->start == NULL) + { + // module has no _start() routine, + // return child = -1 + break; + } child = task_create(module->start, (void*) msg->data[1]); break; @@ -103,5 +109,5 @@ void vfs_main(void* unused) msg_free(msg); break; } - } + } // end while(1) } diff --git a/src/usr/example/example.C b/src/usr/example/example.C index 632eb6882..290d8abc4 100644 --- a/src/usr/example/example.C +++ b/src/usr/example/example.C @@ -12,9 +12,12 @@ trace_desc_t *g_trac_test = NULL; TRAC_INIT(&g_trac_test, "EXAMPLE", 4096); extern "C" -void _start(void*) +void _start(void *ptr) { - printk("Executing example module.\n"); + /** + * @todo fix printk to accept (NULL) + */ + printk( "Executing Example module, arg=%s\n", ( (ptr==NULL) ? "(NULL)" : (char*)ptr ) ); task_end(); } diff --git a/src/usr/initservice/initservice.C b/src/usr/initservice/initservice.C new file mode 100644 index 000000000..6fe759ed0 --- /dev/null +++ b/src/usr/initservice/initservice.C @@ -0,0 +1,418 @@ +/** + * @file initservice.C + * + * Implements Initialization Service for Host boot. + * See initservice.H for details + * + */ + +#include <kernel/console.H> +#include <sys/vfs.h> +#include <sys/task.h> +#include <trace/interface.H> +#include <errl/errlentry.H> + +#include "initservice.H" + + + +namespace INITSERVICE +{ + +// always set up a trace buffer +trace_desc_t *g_trac_errl = NULL; +TRAC_INIT(&g_trac_errl, "INITSERVICE", 4096); + + +/******************************************************************************/ +// InitService::getTheInstance return the only instance +/******************************************************************************/ +InitService& InitService::getTheInstance() +{ + return Singleton<InitService>::instance(); +} + +/******************************************************************************/ +// InitService::Initservice constructor +/******************************************************************************/ +InitService::InitService() +{ + +} + +/******************************************************************************/ +// InitService::~InitService destructor +/******************************************************************************/ +InitService::~InitService() +{ + +} + +/** + * @todo failure to start a task is considered FATAL, revisit later. + */ + +tid_t InitService::startTask( const TaskInfo &i_rtask, errlHndl_t &io_rerrl ) const +{ + tid_t tidrc = 0; + + + if ( i_rtask.taskflags.startflag ) + { + TRACFCOMP(INITSERVICE::g_trac_errl, "startflag is on, starting task...\n" ); + printk( "startflag is on, starting task %s\n", i_rtask.taskname ); + tidrc = task_exec( i_rtask.taskname, NULL ); + if ( (int16_t)tidrc < 0 ) + { + + io_rerrl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_CRITICAL_SYS_TERM, + i_rtask.taskflags.module_id, + INITSERVICE::START_TASK_FAILED, + 0, + 0 + ); + TRACFCOMP(INITSERVICE::g_trac_errl, "ERROR %d starting task, errlog p = %p\n", + tidrc, io_rerrl ); + + } // endif tidrc + else + { + TRACFCOMP(INITSERVICE::g_trac_errl, "task number %d started. errlog p = %p\n", + tidrc, io_rerrl ); + } + } + + return tidrc; +} + +/** + * @todo commit the error log here, and then delete it + * @todo dump some or all of the error log so we know who died. + * + */ +void InitService::reportError(errlHndl_t &io_rerrl ) const +{ + + TRACFCOMP(INITSERVICE::g_trac_errl, "reportError!!!"); + + if ( io_rerrl == NULL ) + { + TRACFCOMP(INITSERVICE::g_trac_errl, "ERROR: reportError was passed a NULL errorlog handle.\n"); + } + else + { + + TRACFCOMP(INITSERVICE::g_trac_errl, + "TODO: commit the error log. delete errl and set to NULL for now.\n" + ); + /** + + * @todo cannot commit an error log until the errorlog service is started up. + * do some checking here + * @todo commit the error log here, note that the commit should delete the log and + * set the handle to NULL + */ + + delete( io_rerrl ); + io_rerrl = NULL; // $$TODO set errl back to NULL for now so all the tasks run + } + + return; +} + + +void InitService::start( void *i_ptr ) +{ + errlHndl_t errl = NULL; // steps will return an error handle if failure + + TRACFCOMP(INITSERVICE::g_trac_errl, "+++++ Initialization Service is starting." ); + + // ---------------------------------------------------------------- + // Start up any tasks necessary in the base modules... + // ---------------------------------------------------------------- + do { + + // startTrace + TRACFCOMP(INITSERVICE::g_trac_errl, "running startTrace..."); + startTrace( errl ); + if ( errl ) + { + TRACFCOMP(INITSERVICE::g_trac_errl, "startTrace failed"); + break; // break out and report error + } + + // startErrorLog + TRACFCOMP(INITSERVICE::g_trac_errl, "running startErrLog..."); + startErrLog( errl ); + if ( errl ) + { + TRACFCOMP(INITSERVICE::g_trac_errl, "startErrLog failed"); + break; // break out and report error + } + + // startXSCOM + TRACFCOMP(INITSERVICE::g_trac_errl, "running startXSCOM..."); + startXSCOMDD( errl ); + if ( errl ) + { + TRACFCOMP(INITSERVICE::g_trac_errl, "startSCOMDD failed"); + break; // break out and report error + } + + // startPNOR + TRACFCOMP( INITSERVICE::g_trac_errl, "running startPNORDD"); + startPNORDD( errl ); + if ( errl ) + { + TRACFCOMP( INITSERVICE::g_trac_errl, "startPNOR failed"); + break; // break out and report error + } + + // startVFS_2 + TRACFCOMP( INITSERVICE::g_trac_errl, "running startVFS_2"); + startVFS_2( errl ); + if ( errl ) + { + TRACFCOMP( INITSERVICE::g_trac_errl, "startVFS_2 failed"); + break; // break out and report error + } + + } while( false ); + + + /** + * @todo stop here now if someone posted an error log, revisit this + * when we know what to do. + */ + if ( errl ) + { + TRACFCOMP(INITSERVICE::g_trac_errl, "Errorlog posted, commit and die."); + reportError( errl ); + } + + assert( errl == NULL ); + + + // ---------------------------------------------------------------- + // start running the extended modules + // ---------------------------------------------------------------- + do { + // startTargetting + TRACFCOMP( INITSERVICE::g_trac_errl, "running startTargetting"); + startTargetting( errl ); + if ( errl ) + { + TRACFCOMP( INITSERVICE::g_trac_errl, "startTargetting failed"); + + break; // break out and report error + } + + // getMasterChipTarget + TRACFCOMP( INITSERVICE::g_trac_errl, "running getMasterChipTarget"); + getMasterChipTarget( errl ); + if ( errl ) + { + TRACFCOMP( INITSERVICE::g_trac_errl, "getMasterChipTarget failed"); + + break; // break out and report error + } + + // startMailboxDD + TRACFCOMP( INITSERVICE::g_trac_errl, "running startMailboxDD"); + startMailboxDD( errl ); + if ( errl ) + { + TRACFCOMP( INITSERVICE::g_trac_errl, "startMailboxDD failed"); + + break; // break out and report error + } + + // startSPComm + TRACFCOMP( INITSERVICE::g_trac_errl, "running startSPComm"); + startSPComm( errl ); + if ( errl ) + { + TRACFCOMP( INITSERVICE::g_trac_errl, "startSPComm failed"); + + break; // break out and report error + } + + // enableStreamingTrace + TRACFCOMP( INITSERVICE::g_trac_errl, "running enableStreamingTrace"); + enableStreamingTrace( errl ); + if ( errl ) + { + TRACFCOMP( INITSERVICE::g_trac_errl, "enableStreamingTrace failed"); + + break; // break out and report error + } + + // startProgressCodes + TRACFCOMP( INITSERVICE::g_trac_errl, "running startProgressCodes"); + startProgressCodes( errl ); + if ( errl ) + { + TRACFCOMP( INITSERVICE::g_trac_errl, "startProgressCodes failed"); + + break; // break out and report error + } + + // startFSIDD + TRACFCOMP( INITSERVICE::g_trac_errl, "running startFSIDD"); + startFSIDD( errl ); + if ( errl ) + { + TRACFCOMP( INITSERVICE::g_trac_errl, "startFSIDD failed"); + + break; // break out and report error + } + + // setupSlaveLinks + TRACFCOMP( INITSERVICE::g_trac_errl, "running setupSlaveLinks"); + setupSlaveLinks( errl ); + if ( errl ) + { + TRACFCOMP( INITSERVICE::g_trac_errl, "setupSlaveLinks failed"); + + break; // break out and report error + } + + // startFSISCOM + TRACFCOMP( INITSERVICE::g_trac_errl, "running startFSISCOM"); + startFSISCOM( errl ); + if ( errl ) + { + TRACFCOMP( INITSERVICE::g_trac_errl, "startFSISCOM failed"); + + break; // break out and report error + } + + // startFSII2C + TRACFCOMP( INITSERVICE::g_trac_errl, "running startFSII2C"); + startFSII2C( errl ); + if ( errl ) + { + TRACFCOMP( INITSERVICE::g_trac_errl, "startFSII2C failed"); + + break; // break out and report error + } + + // startHWP + TRACFCOMP( INITSERVICE::g_trac_errl, "running startHWP"); + startHWPF( errl ); + if ( errl ) + { + TRACFCOMP( INITSERVICE::g_trac_errl, "startHWP failed"); + + break; // break out and report error + } + + // readMaxConfigfromPNOR + TRACFCOMP( INITSERVICE::g_trac_errl, "running readMaxConfigfromPNOR"); + readMaxConfigfromPNOR( errl ); + if ( errl ) + { + TRACFCOMP( INITSERVICE::g_trac_errl, "readMaxConfigfromPNOR failed"); + + break; // break out and report error + } + + // applyPresenceDetect + TRACFCOMP( INITSERVICE::g_trac_errl, "running applyPresenceDetect"); + applyPresenceDetect( errl ); + if ( errl ) + { + TRACFCOMP( INITSERVICE::g_trac_errl, "applyPresenceDetect failed"); + + break; // break out and report error + } + + // applyPartialBad + TRACFCOMP( INITSERVICE::g_trac_errl, "running applyPartialBad"); + applyPartialBad( errl ); + if ( errl ) + { + TRACFCOMP( INITSERVICE::g_trac_errl, "applyPartialBad failed"); + + break; // break out and report error + } + + // applyGard + TRACFCOMP( INITSERVICE::g_trac_errl, "running applyGard..."); + applyGard( errl ); + if ( errl ) + { + + TRACFCOMP( INITSERVICE::g_trac_errl, "applyGard failed"); + break; // break out and report error + } + + // collectHWIDEC + TRACFCOMP( INITSERVICE::g_trac_errl, "running collectHWIDEC..."); + collectHWIDEC( errl ); + if ( errl ) + { + TRACFCOMP( INITSERVICE::g_trac_errl, "collectHWIDEC failed"); + + break; // break out and report error + } + + // verifyIDEC + TRACFCOMP( INITSERVICE::g_trac_errl, "running verifyIDEC"); + verifyIDEC( errl ); + if ( errl ) + { + TRACFCOMP( INITSERVICE::g_trac_errl, "verifyIDEC failed"); + + break; // break out and report error + } + + // disableWatchDog + TRACFCOMP( INITSERVICE::g_trac_errl, "running disableWatchDog"); + disableWatchDog( errl ); + if ( errl ) + { + TRACFCOMP( INITSERVICE::g_trac_errl, "disableWatchDog failed"); + + break; // break out and report error + } + + + } while ( false ); + + + /** + * @todo stop here now if someone posted an error log, revisit this + * when we know what to do. + */ + if ( errl ) + { + TRACFCOMP(INITSERVICE::g_trac_errl, "Errorlog posted, commit and die."); + reportError( errl ); + } + + assert( errl == NULL ); + + + + // executeISteps + TRACFCOMP( INITSERVICE::g_trac_errl, "running executeISteps"); + executeISteps( errl ); + + if ( errl ) + { + TRACFCOMP( INITSERVICE::g_trac_errl, "executeISteps failed"); + reportError( errl ); + assert( errl == NULL ); + } + + + TRACFCOMP( INITSERVICE::g_trac_errl, "+++++ Initilization Service finished. IN THE REAL CODE WE WILL NEVER GET HERE"); + + // return to _start(), which may end the task or die. + return; +} + + +} // namespace INITSERVICE diff --git a/src/usr/initservice/initservice.H b/src/usr/initservice/initservice.H new file mode 100644 index 000000000..0e880de1a --- /dev/null +++ b/src/usr/initservice/initservice.H @@ -0,0 +1,448 @@ +/** + * @file initservice.H + * + * - Manage high-level host boot IPL flow + * - Perform can-continue processing + * - Perform automatic and manual Istep execution + * - Handle flow errors as appropriate. + * + */ + +/** + * High-level todo list + * + * @todo SP3: move startTask() and reportError() to private + * @todo SP3: remove ADUDD, not used + * @todo SP3: add (NULL) detection to printk + * @todo SP3: reevaluate all trace calls - TRACF are field traces, - ERR_MRK etc macros + * @todo SP3: change InitService::start() to init(), document this as a standard. + * @todo SP3: initservice/makefile remove trailing tabs + * @todo SP3: Disable copy CTOR/assignment operator; this would have caught an illegal copy by assignment elsewhere + * @@todo Add more macros to trace, discuss with Andrew and Nick + * + * + */ + +#ifndef __INIT_SERVICE_H +#define __INIT_SERVICE_H + +/******************************************************************************/ +// Includes +/******************************************************************************/ +#include <stdint.h> +#include <util/singleton.H> +#include <sys/vfs.h> // VFS_MODULE_NAME_MAX + +#include <errl/errlentry.H> +#include <initservice/initsvcreasoncodes.H> + +namespace INITSERVICE +{ + +/******************************************************************************/ +// Globals/Constants +/******************************************************************************/ + +/******************************************************************************/ +// Typedef/Enumerations +/******************************************************************************/ +/** + * @enum ModuleType + * - BASE_MODULE == module in the base image + * - EXT_MODULE == module in the extended image + */ +enum ModuleType +{ + BASE_MODULE = 0, + EXT_MODULE, +}; + + +/** + * @struct TaskFlags + * + * - run _start() function on start + * - module type, BASE_MODULE or EXT_MODULE + * - module_id for errorlog if task fails + * + * @todo revisit these flags in sprint3 + */ +struct TaskFlags +{ + bool startflag; // this is a task, run _start() function + ModuleType module_type; // BASE_MODULE_TYPE or EXT_MODULE_TYPE + InitServiceModuleID module_id; // module id for errorlog +}; + +/** + * @struct _TaskInfo + * + * Holds information on each task in the system. + * - taskname + * - execution flags, see TaskFlags above + * + */ +struct TaskInfo +{ + const char taskname[VFS_MODULE_NAME_MAX]; + TaskFlags taskflags; + +} PACKED; + + +/******************************************************************************/ +// InitService Class +/******************************************************************************/ + +// Singleton definition +class InitService; +typedef Singleton<InitService> theInitService; + +/** + * @class InitService Singleton Class + * + * This class is launched by _start() (see initservicetaskentry.C), + * which is launched by the kernel (init_main.C). + * + * Once started, it handles the rest of HostBoot Initialization. + * + * @returns none + */ +class InitService +{ + +public: + + friend class InitServiceTest; + + /** + * @brief Get singleton instance of this class. + * + * @return the (one and only) instance of InitService + */ + static InitService& getTheInstance(); + + /** + * @brief Provide an entry function into the class, called from _start() + * + * @param[in] i_args pointer to any arguments passed in from + * _start() and by extension the kernel, + * currently this is NULL . + * + * @todo Sprint 3: pass in ptr to errorlog struct? + * @todo document any changes for args + */ + void start( void *i_args); + + /** + * @brief Constructor for the InitService object. + */ + InitService(); + + /** + * @brief Destructor for the InitService object. + */ + ~InitService(); + + /** + * @brief start a task + * + * @param[in] i_rtask reference to a TaskInfo struct + * @param[inout] i_rerrl reference to an errorlog struct. + * struct will be filled out if error, + * otherwise untouched. + * + * @return child id if success, < 0 for failure + * + * @todo return errorlog handle in sprint3 + */ + tid_t startTask( const TaskInfo &i_rtask, errlHndl_t &i_rerrl ) const; + + /** + * @brief report Error to the system. + * + * @param[in] io_errl - errlHndl_t pointer to a filled-out error entry + * errorlog will be committed, errorlog + * will be deleted, and pointer will be + * set to NULL on exit + * + * @return nothing + */ + void reportError( errlHndl_t &io_rerrl) const; + + +private: + + + + /** + * @brief Initialize the Trace module + * + * @param[in,out] i_rerrl - errorlog handle. + * Success: handle is untouched + * Failure: will point to a filled-out errorlog + * + * @return none + */ + void startTrace( errlHndl_t &i_rerrl ) const; + + /** + * @brief Initialize the ErrorLog module + * + * * + * @param[in,out] i_rerrl - errorlog handle. + * Success: handle is untouched + * Failure: will point to a filled-out errorlog + * + * @return none + */ + void startErrLog( errlHndl_t &i_rerrl ) const; + + /** + * @brief Initialize the XSCOM Device Driver module + * + * @param[in,out] i_rerrl - errorlog handle. + * Success: handle is untouched + * Failure: will point to a filled-out errorlog + * + * @return none + */ + void startXSCOMDD( errlHndl_t &i_rerrl ) const; + + /** + * @brief Initialize the PNOR Device Driver module + * + * @param[in,out] i_rerrl - errorlog handle. + * Success: handle is untouched + * Failure: will point to a filled-out errorlog + * + * @return none + */ + void startPNORDD( errlHndl_t &i_rerrl ) const; + + /** + * @brief Initialize the second stage of VFS module + * @param[in,out] i_rerrl - errorlog handle. + * Success: handle is untouched + * Failure: will point to a filled-out errorlog + * + * @return none + */ + + void startVFS_2( errlHndl_t &i_rerrl ) const; + + /** + * @brief Initialize the Targetting DD module + * + * @param[in,out] i_rerrl - errorlog handle. + * Success: handle is untouched + * Failure: will point to a filled-out errorlog + * + * @return none + */ + void startTargetting( errlHndl_t &i_rerrl ) const; + + /** + * @brief get the Master Chip Target + * + * @param[in,out] i_rerrl - errorlog handle. + * Success: handle is untouched + * Failure: will point to a filled-out errorlog + * + * @return none + */ + void getMasterChipTarget( errlHndl_t &i_rerrl ) const; + + /** + * @brief Initialize the Mailbox Device Driver + * + * @param[in,out] i_rerrl - errorlog handle. + * Success: handle is untouched + * Failure: will point to a filled-out errorlog + * + * @return none + */ + void startMailboxDD( errlHndl_t &i_rerrl ) const; + + /** + * @brief Initialize SP Communications + * + * @param[in,out] i_rerrl - errorlog handle. + * Success: handle is untouched + * Failure: will point to a filled-out errorlog + * + * @return none + */ + void startSPComm( errlHndl_t &i_rerrl ) const; + + /** + * @brief Turn on Streaming Trace, if the PNOR flag is set + * + * @param[in,out] i_rerrl - errorlog handle. + * Success: handle is untouched + * Failure: will point to a filled-out errorlog + * + * @return none + */ + void enableStreamingTrace( errlHndl_t &i_rerrl ) const; + + /** + * @brief Start reporting progress codes. + * + * @param[in,out] i_rerrl - errorlog handle. + * Success: handle is untouched + * Failure: will point to a filled-out errorlog + * + * @return none + */ + void startProgressCodes( errlHndl_t &i_rerrl ) const; + + /** + * @brief Initialize the FSI Device Driver module + * + * @param[in,out] i_rerrl - errorlog handle. + * Success: handle is untouched + * Failure: will point to a filled-out errorlog + * + * @return none + */ + void startFSIDD( errlHndl_t &i_rerrl ) const; + + /** + * @brief Set up links to the slaves + * + * @param[in,out] i_rerrl - errorlog handle. + * Success: handle is untouched + * Failure: will point to a filled-out errorlog + * + * @return none + */ + void setupSlaveLinks( errlHndl_t &i_rerrl ) const; + + /** + * @brief Initialize FSI SCOM + * + * @param[in,out] i_rerrl - errorlog handle. + * Success: handle is untouched + * Failure: will point to a filled-out errorlog + * + * @return none + */ + void startFSISCOM( errlHndl_t &i_rerrl ) const; + + /** + * @brief Initialize FSI I2C + * + * @param[in,out] i_rerrl - errorlog handle. + * Success: handle is untouched + * Failure: will point to a filled-out errorlog + * + * @return none + */ + void startFSII2C( errlHndl_t &i_rerrl ) const; + + /** + * @brief Initialize HWP + * + * @param[in,out] i_rerrl - errorlog handle. + * Success: handle is untouched + * Failure: will point to a filled-out errorlog + * + * @return none + */ + void startHWPF( errlHndl_t &i_rerrl ) const; + + /** + * @brief Read Configuration from PNOR + * + * @param[in,out] i_rerrl - errorlog handle. + * Success: handle is untouched + * Failure: will point to a filled-out errorlog + * + * @return none + */ + void readMaxConfigfromPNOR( errlHndl_t &i_rerrl ) const; + + /** + * @brief apply Presence Detect + * + * @param[in,out] i_rerrl - errorlog handle. + * Success: handle is untouched + * Failure: will point to a filled-out errorlog + * + * @return none + */ + void applyPresenceDetect( errlHndl_t &i_rerrl ) const; + + /** + * @brief apply Partial Bad + * + * @param[in,out] i_rerrl - errorlog handle. + * Success: handle is untouched + * Failure: will point to a filled-out errorlog + * + * @return none + */ + void applyPartialBad( errlHndl_t &i_rerrl ) const; + /** + * @brief apply Gard + * + * @param[in,out] i_rerrl - errorlog handle. + * Success: handle is untouched + * Failure: will point to a filled-out errorlog + * + * @return none + */ + void applyGard( errlHndl_t &i_rerrl ) const; + + /** + * @brief Collect HW IDEC info + * + * @param[in,out] i_rerrl - errorlog handle. + * Success: handle is untouched + * Failure: will point to a filled-out errorlog + * + * @return none + */ + void collectHWIDEC( errlHndl_t &i_rerrl ) const; + + /** + * @brief verify the IDEC info + * + * @param[in,out] i_rerrl - errorlog handle. + * Success: handle is untouched + * Failure: will point to a filled-out errorlog + * + * @return none + */ + void verifyIDEC( errlHndl_t &i_rerrl ) const; + + /** + * @brief Disable the HW watchdog + * + * @param[in,out] i_rerrl - errorlog handle. + * Success: handle is untouched + * Failure: will point to a filled-out errorlog + * + * @return none + */ + void disableWatchDog( errlHndl_t &i_rerrl ) const; + + /** + * @brief Execute the IStep module to communicate with SP and run + * the isteps. + * + * @param[in,out] i_rerrl - errorlog handle. + * Success: handle is untouched + * Failure: will point to a filled-out errorlog + * + * @return none + */ + void executeISteps( errlHndl_t &i_rerrl ) const; + + +}; // class InitService + +} // namespace INITSERVICE + +#endif diff --git a/src/usr/initservice/initservicetaskentry.C b/src/usr/initservice/initservicetaskentry.C new file mode 100644 index 000000000..0fb84e00d --- /dev/null +++ b/src/usr/initservice/initservicetaskentry.C @@ -0,0 +1,67 @@ +/** + * @file initservicetaskentry.C + * task entry point for Initialization Service. + * init_main.C will call this by executing + * task_exec( "libinitservice.so", NULL ); + * From there we can execute the classes that will run in the task. + * + * At the end, we must run task_end(). + */ +#include <kernel/console.H> +#include <sys/vfs.h> +#include <sys/task.h> +#include <trace/interface.H> +#include <errl/errlentry.H> + +#include "initservice.H" + + + +namespace INITSERVICE +{ + +/** + * @brief task entry routine, called by init_main.C + * + */ + +extern "C" +void _start(void *ptr) +{ + tid_t tidrc = 0; + + printk("===== Executing Initialization Service modules\n" ); + + + // create an instance of InitService + InitService::InitService& is = InitService::getTheInstance(); + + // initialize the base modules in Hostboot. + is.start( ptr ); + + + + // ----- run unit tests and example code, if present ---------------- + /** + * @todo remove this eventually, figure out where to run UnitTests. + */ + printk("===== Executing Unit Tests\n" ); + + // run unit tests if present (i.e. we are running hbicore_test.bin) + tidrc = task_exec("libcxxtest.so", NULL); + + /** + * @todo barrier here to wait for all the tests to finish... + */ + + printk( "===== Done, terminating Initialization service..."); + + /** + * @todo add assert(0) here??? + */ + + + task_end(); +} + +} // INITSERVICE diff --git a/src/usr/initservice/initservicevfs1.C b/src/usr/initservice/initservicevfs1.C new file mode 100644 index 000000000..691fef197 --- /dev/null +++ b/src/usr/initservice/initservicevfs1.C @@ -0,0 +1,69 @@ +/** + * @file initservicevfs1.C + * + * Private functions for VFS1 phase. + */ + +#include <kernel/console.H> +#include <sys/vfs.h> +#include <sys/task.h> +#include <trace/interface.H> + +#include "initservice.H" + +#include "initsvctasks.H" + + +namespace INITSERVICE +{ + +/******************************************************************************/ +// private functions for VFS 1 phase +/******************************************************************************/ + +void InitService::startTrace( errlHndl_t &io_rerrl ) const +{ + + // start up the task + startTask( TASK_TRACE, io_rerrl ); + + return; +} + + +void InitService::startErrLog( errlHndl_t &io_rerrl ) const +{ + + startTask( TASK_ERRORLOG, io_rerrl ); + + return; +} + + +void InitService::startXSCOMDD( errlHndl_t &io_rerrl ) const +{ + + startTask( TASK_XSCOMDD, io_rerrl ); + + return; +} + + +void InitService::startPNORDD( errlHndl_t &io_rerrl ) const +{ + + startTask( TASK_PNORDD, io_rerrl ); + + return; +} + + +void InitService::startVFS_2( errlHndl_t &io_rerrl ) const +{ + + startTask( TASK_VFS_2, io_rerrl ); + + return; +} + +} // namespace INITSERVICE diff --git a/src/usr/initservice/initservicevfs2.C b/src/usr/initservice/initservicevfs2.C new file mode 100644 index 000000000..46c49e988 --- /dev/null +++ b/src/usr/initservice/initservicevfs2.C @@ -0,0 +1,176 @@ +/** + * @file initservicevfs2.C + * + * Private functions for VFS2 phase. + */ + +#include <kernel/console.H> +#include <sys/vfs.h> +#include <sys/task.h> +#include <trace/interface.H> + +#include "initservice.H" + +#include "initsvctasks.H" + + +namespace INITSERVICE +{ + + +/******************************************************************************/ +// private functions for VFS 2 phase +/******************************************************************************/ + + +void InitService::startTargetting( errlHndl_t &io_rerrl ) const +{ + + + return; +} + + + void InitService::getMasterChipTarget( errlHndl_t &io_rerrl ) const +{ + + + return; +} + + + void InitService::startMailboxDD( errlHndl_t &io_rerrl ) const +{ + + + return; +} + + + void InitService::startSPComm( errlHndl_t &io_rerrl ) const +{ + + + return; +} + + + void InitService::enableStreamingTrace( errlHndl_t &io_rerrl ) const +{ + + + return; +} + + + void InitService::startProgressCodes( errlHndl_t &io_rerrl ) const +{ + + return; + +} + + + void InitService::startFSIDD( errlHndl_t &io_rerrl ) const +{ + + + return; +} + + + void InitService::setupSlaveLinks( errlHndl_t &io_rerrl ) const +{ + + + return; +} + + + void InitService::startFSISCOM( errlHndl_t &io_rerrl ) const +{ + + + return; +} + + + void InitService::startFSII2C( errlHndl_t &io_rerrl ) const +{ + + + return; +} + + + void InitService::startHWPF( errlHndl_t &io_rerrl ) const +{ + + + return; +} + + + void InitService::readMaxConfigfromPNOR( errlHndl_t &io_rerrl ) const +{ + + + return; +} + + +void InitService::applyPresenceDetect( errlHndl_t &io_rerrl ) const +{ + + + return; +} + + + void InitService::applyPartialBad( errlHndl_t &io_rerrl ) const +{ + + + return; +} + +void InitService::applyGard( errlHndl_t &io_rerrl ) const +{ + + + return; +} + + +void InitService::collectHWIDEC( errlHndl_t &io_rerrl ) const +{ + + + return; +} + + + void InitService::verifyIDEC( errlHndl_t &io_rerrl ) const +{ + + + return; +} + + + void InitService::disableWatchDog( errlHndl_t &io_rerrl ) const +{ + + + return; +} + + + void InitService::executeISteps( errlHndl_t &io_rerrl ) const +{ + + + return; +} + +} // namespace INITSERVICE diff --git a/src/usr/initservice/initsvctasks.H b/src/usr/initservice/initsvctasks.H new file mode 100644 index 000000000..4f8c48656 --- /dev/null +++ b/src/usr/initservice/initsvctasks.H @@ -0,0 +1,79 @@ +/** + * @file initsvctasks.H + * + * TaskInfo structs for each task that will run. + */ + +#ifndef __INIT_SVC_TASKS_H +#define __INIT_SVC_TASKS_H + +#include <initservice/initsvcreasoncodes.H> +#include "initservice.H" + +namespace INITSERVICE +{ + + +/** + * @brief Trace Task + */ +const TaskInfo TASK_TRACE = { + "libtrace.so" , // taskname + { false, // don't start + BASE_MODULE, // Base Module + START_TRACE_ID, // module id for errorlog + }, +}; + + +/** + * @brief Errorlog Task + */ +const TaskInfo TASK_ERRORLOG = { + "liberrl.so" , // taskname + { false, // don't start + BASE_MODULE, // Base Module + START_ERRL_ID, // module id for errorlog + + }, +}; + + +/** + * @brief XSCOM Task + */ +const TaskInfo TASK_XSCOMDD = { + "libscom.so" , // taskname + { false, // don't start + BASE_MODULE, // Base Module + START_XSCOMDD_ID, // module id for errorlog + }, +}; + + +/** + * @brief PNOR Driver Task + */ +const TaskInfo TASK_PNORDD = { + "libpnordd.so" , // taskname + { false, // don't start + BASE_MODULE, // Base Module + START_PNORDD_ID, // module id for errorlog + }, +}; + + +/** + * @brief VFS 2 task, initializes extended module area + */ +const TaskInfo TASK_VFS_2 = { + "vfs2.so" , // taskname + { false, // don't start + BASE_MODULE, // Base Module + START_VFS_2_ID // module id for errorlog + }, +}; + + +}; // namespace INITSERVICE +#endif // __INIT_SVC_TASKS_H diff --git a/src/usr/initservice/makefile b/src/usr/initservice/makefile new file mode 100644 index 000000000..085805786 --- /dev/null +++ b/src/usr/initservice/makefile @@ -0,0 +1,11 @@ +ROOTPATH = ../../.. +MODULE = initservice + +OBJS = initservice.o \ + initservicetaskentry.o \ + initservicevfs1.o \ + initservicevfs2.o + +SUBDIRS = test.d + +include ${ROOTPATH}/config.mk diff --git a/src/usr/initservice/test/initservicetest.H b/src/usr/initservice/test/initservicetest.H new file mode 100644 index 000000000..3edfa2885 --- /dev/null +++ b/src/usr/initservice/test/initservicetest.H @@ -0,0 +1,237 @@ +/** + * @file initservicetest.H + * + * Private functions for VFS2 phase. + */ + +#ifndef __TEST_INIT_SERVICETEST_H +#define __TEST_INIT_SERVICETEST_H + +/** + * @file initservicetest.H + * + * @brief Unit tests for initservice module + */ + +#include <cxxtest/TestSuite.H> + +#include "../initservice.H" + +/** + * @brief set up a dummy TaskInfo struct for test 1. + * this taskname should not exist, so we are expecting an error log back. + * + */ +const INITSERVICE::TaskInfo TASK_TEST1 = { + "libtestinitsvc_noexist.so" , // taskname + { + true, // startflag=true, try to start + INITSERVICE::BASE_MODULE, // Base Module + INITSERVICE::INIT_SVC_TEST1_ID, // module id for errorlog + }, +}; + + +/** + * @brief set up a dummy TaskInfo struct for test 2. + * example.C does indeed have a _start() function so this should return OK. + * + * @todo this needs to be replaced with a test module + */ +const INITSERVICE::TaskInfo TASK_TEST2 = { + "libexample.so" , // taskname + { + true, // startflag=true, try to start + INITSERVICE::BASE_MODULE, // Base Module + INITSERVICE::INIT_SVC_TEST2_ID, // module id for errorlog + }, +}; + + +/** + * @brief set up a dummy TaskInfo struct. + * libtrace does NOT have a _start() function so this should return an errorlog. + * + * @todo this needs to be replaced with a test module + */ +const INITSERVICE::TaskInfo TASK_TEST3 = { + "libtrace.so" , // taskname + { + true, // startflag=true, try to start + INITSERVICE::BASE_MODULE, // Base Module + INITSERVICE::INIT_SVC_TEST3_ID, // module id for errorlog + }, +}; + +/** + * @class InitServiceTest + * + * runs unit testa against InitService class + * + */ +class InitServiceTest: public CxxTest::TestSuite +{ + +public: + /** + * @brief testInitServiceStartTask1 + * this should try to run a nonexistent task, return an + * errorlog, and not blow up + * + */ + void testInitServiceStartTask1(void) + { + errlHndl_t errl = NULL; + /** + * @todo use a separate instance here, not the singleton + */ + INITSERVICE::InitService &l_is = INITSERVICE::InitService::getTheInstance(); + tid_t tidrc = 0; + + + TS_TRACE( "=====>Attempt to run a nonexistent task.\n "); + tidrc = l_is.startTask( TASK_TEST1, errl ); + printk( "testInitServiceStartTask1: startTask returned %d: errl=%p\n", tidrc, errl ); + if ( (int16_t)tidrc < 0 ) + { + TS_TRACE( "SUCCESS: startTask returned an errorlog.\n"); + // @todo dump error log to trace? + } + else + { + TS_FAIL( "ERROR: no error log was returned.\n"); + } + + + return; + } + + /** + * @brief testInitServiceStartTask2 + * this should try to run a task that does have a _start() function. + * it should return OK. + */ + void testInitServiceStartTask2(void) + { + errlHndl_t errl = NULL; + /** + * @todo use a separate instance here, not the singleton + */ + INITSERVICE::InitService &l_is = INITSERVICE::InitService::getTheInstance(); + tid_t tidrc = 0; + + + TS_TRACE( "=====>Attempt to run a task with a _start() function.\n "); + tidrc = l_is.startTask( TASK_TEST2, errl ); + printk( "testInitServiceStartTask2: startTask returned %d: errl=%p\n", tidrc, errl ); + if ( (int16_t)tidrc >= 0 ) + { + TS_TRACE( "SUCCESS: startTask returned OK.\n"); + // @todo dump error log to trace? + } + else + { + TS_FAIL( "ERROR: StartTask returned an error log.\n"); + } + + + return; + } + + + /** + * @brief testInitServiceStartTask3 + * this should try to run a task that does NOT have a _start() function. + * it should fail + */ + void testInitServiceStartTask3(void) + { + errlHndl_t errl = NULL; + /** + * @todo use a separate instance here, not the singleton + */ + INITSERVICE::InitService &l_is = INITSERVICE::InitService::getTheInstance(); + tid_t tidrc = 0; + + + TS_TRACE( "====>Attempt to run a task with NO _start() function.\n "); + tidrc = l_is.startTask( TASK_TEST3, errl ); + printk( "testInitServiceStartTask3: startTask returned %d: errl=%p\n", tidrc, errl ); + if ( (int16_t)tidrc < 0 ) + { + TS_TRACE( "SUCCESS: startTask returned an error log.\n"); + // @todo dump error log to trace? + } + else + { + TS_FAIL( "ERROR: StartTask did not return an error log.\n"); + } + + return; + } + + /** + * @brief testInitServicereportError1 + * This will call reportError with a NULL errlHndl_t . It should handle it + * OK (reportError() will print an error message to trace) + */ + void testInitServicereportError1(void) + { + errlHndl_t errl = NULL; + /** + * @todo use a separate instance here, not the singleton + */ + INITSERVICE::InitService &l_is = INITSERVICE::InitService::getTheInstance(); + + TS_TRACE( "====> call reportError with NULL handle, should handle it OK\n "); + l_is.reportError( errl ); + + // reportError() might crash, if it returns, just make sure it didn't modify + // the input pointer + if ( errl != NULL) + { + TS_FAIL( "ERROR: expected the NULL errlHndl_t to stay NULL\n"); + } + + return; + } + + /** + * @brief testInitServicereportError1 + * This will call reportError with a good errorlog. + * on return, it should be NULLED out + * @todo can we check with the errorlogging facility to see if it got + * posted?? + */ + void testInitServicereportError2(void) + { + errlHndl_t errl = NULL; + /** + * @todo use a separate instance here, not the singleton + */ + INITSERVICE::InitService &l_is = INITSERVICE::InitService::getTheInstance(); + + errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_INFORMATIONAL, + INITSERVICE::INIT_SVC_TEST5_ID, + INITSERVICE::START_TASK_FAILED, + 0, + 0 + ); + + TS_TRACE( "====> call reportError with good error handle, should commit and then delete\n "); + l_is.reportError( errl ); + if ( errl !=NULL ) + { + TS_FAIL( "ERROR: reportError did not delete the errlHndl_t handle!\n" ); + } + + + + return; + } +}; // class InitServiceTest + + +#endif // __TEST_INIT_SERVICETEST_H + diff --git a/src/usr/initservice/test/makefile b/src/usr/initservice/test/makefile new file mode 100644 index 000000000..350257803 --- /dev/null +++ b/src/usr/initservice/test/makefile @@ -0,0 +1,6 @@ +ROOTPATH = ../../../.. + +MODULE = testinitservice +TESTS = *.H + +include ${ROOTPATH}/config.mk diff --git a/src/usr/makefile b/src/usr/makefile index 0f0ec8e65..ec5d3d7e6 100644 --- a/src/usr/makefile +++ b/src/usr/makefile @@ -3,6 +3,6 @@ ROOTPATH = ../.. OBJS = module_init.o SUBDIRS = example.d trace.d cxxtest.d testcore.d errl.d devicefw.d \ - scom.d xscom.d targeting.d + scom.d xscom.d targeting.d initservice.d include ${ROOTPATH}/config.mk |