diff options
| author | Stephen Cprek <smcprek@us.ibm.com> | 2013-06-21 16:34:25 -0700 | 
|---|---|---|
| committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2014-10-16 10:42:46 -0500 | 
| commit | 60a6933fb818b282fb7aa50b4a7f4d98ebd4657f (patch) | |
| tree | 67d0b14ec56b358e004c10526bb61135b7dd6f56 | |
| parent | 1ca3b284749604f3984b002fb292e68e86b1227a (diff) | |
| download | blackbird-hostboot-60a6933fb818b282fb7aa50b4a7f4d98ebd4657f.tar.gz blackbird-hostboot-60a6933fb818b282fb7aa50b4a7f4d98ebd4657f.zip | |
Add human-readable dumps of error log entries as they are committed.
Origin: Google Shared Technology
Change-Id: I1d0a30faa27c0b8bd1b76418706e24378a5da7eb
RTC: 97491
Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/11266
Tested-by: Jenkins Server
Reviewed-by: Brian Silver <bsilver@us.ibm.com>
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
| -rwxr-xr-x | src/build/tools/listdeps.pl | 2 | ||||
| -rw-r--r-- | src/include/usr/errl/errlmanager.H | 123 | ||||
| -rw-r--r-- | src/include/usr/errldisplay/errldisplay.H | 162 | ||||
| -rw-r--r-- | src/makefile | 1 | ||||
| -rw-r--r-- | src/usr/errl/errlmanager.C | 368 | ||||
| -rwxr-xr-x | src/usr/errl/parser/genErrlParsers.pl | 64 | ||||
| -rw-r--r-- | src/usr/errl/parser/makefile | 2 | ||||
| -rw-r--r-- | src/usr/errldisplay/errldisplay.C | 195 | ||||
| -rw-r--r-- | src/usr/errldisplay/makefile | 37 | ||||
| -rw-r--r-- | src/usr/initservice/extinitsvc/extinitsvctasks.H | 17 | ||||
| -rw-r--r-- | src/usr/makefile | 1 | 
11 files changed, 800 insertions, 172 deletions
| diff --git a/src/build/tools/listdeps.pl b/src/build/tools/listdeps.pl index 9e389948c..1bfbad4a7 100755 --- a/src/build/tools/listdeps.pl +++ b/src/build/tools/listdeps.pl @@ -211,7 +211,7 @@ my %resident_modules = (      "libgpio.so"           => '1',      "liblpc.so"            => '1',      "libconsole.so"        => '1', - +    "liberrldisplay.so"    => '1',  );  # has with library to istep list file were the DepMod array is kept diff --git a/src/include/usr/errl/errlmanager.H b/src/include/usr/errl/errlmanager.H index 1063c6bff..02c47a8d2 100644 --- a/src/include/usr/errl/errlmanager.H +++ b/src/include/usr/errl/errlmanager.H @@ -6,6 +6,7 @@  /* OpenPOWER HostBoot Project                                             */  /*                                                                        */  /* Contributors Listed Below - COPYRIGHT 2011,2014                        */ +/* [+] Google Inc.                                                        */  /* [+] International Business Machines Corp.                              */  /*                                                                        */  /*                                                                        */ @@ -34,17 +35,19 @@  /*****************************************************************************/  // I n c l u d e s  /*****************************************************************************/ +#include <config.h>  #include <util/singleton.H>  #include <errl/errlentry.H> +#include <errldisplay/errldisplay.H>  #include <sys/sync.h>  #include <kernel/timemgr.H>  #include <hbotcompid.H>  #include <hwas/common/hwasCallout.H>  #include <mbox/mbox_queues.H>  #include <mbox/mboxif.H> +#include <utility>  #include <list> -  namespace ERRORLOG  { @@ -77,6 +80,7 @@ enum errlManagerNeeds      PNOR,      TARG,      MBOX, +    ERRLDISP,  } ; @@ -216,6 +220,7 @@ private:          ERRLOG_ACCESS_PNOR_TYPE            = 0x00000034 | MBOX::FIRST_SECURE_MSG,          ERRLOG_ACCESS_MBOX_TYPE            = 0x00000035 | MBOX::FIRST_SECURE_MSG,          ERRLOG_ACCESS_TARG_TYPE            = 0x00000036 | MBOX::FIRST_SECURE_MSG, +        ERRLOG_ACCESS_ERRLDISP_TYPE        = 0x00000037 | MBOX::FIRST_SECURE_MSG,      };      /** @@ -293,11 +298,9 @@ private:       * @brief Create a mailbox message with the error log and send it to Fsp.       *       * @param[in,out] io_err Error log handle to be committed -     * @return        msg_t pointer - NULL if msg sent, allocated msg if -     *                  couldn't send       *       */ -    msg_t *sendErrLogToMbox ( errlHndl_t& io_err ); +    void sendErrLogToMbox ( errlHndl_t& io_err );      /**       * @brief Create a mailbox message with the error log and send it to Fsp. @@ -438,13 +441,117 @@ private:      char *iv_pnorAddr;          // HBEL section in PNOR      uint32_t iv_maxErrlInPnor;  // max number of errorlogs that will fit      uint32_t iv_pnorOpenSlot;   // current open slot available for an errorlog -    std::list<errlHndl_t> iv_errlToSave;   // errlogs still to be saved to PNOR -      bool iv_isSpBaseServices;           // do we need to send to FSP      bool iv_isMboxEnabled;              // are we able to send to FSP -    std::list<msg_t *> iv_errlToSend;   // msgs still to be sent to FSP -      bool iv_nonInfoCommitted;   //< Keeps track of any non-informational logs. +    bool iv_isErrlDisplayEnabled;     // are we able to use the errorDisplay + +    // Errl flags which represent processing needed by the errl +    // represented as a bit field (8 bits) +    // Note: When adding a new flag, add to the trace in errlogShutdown() +    enum ERRLOG_FLAGS +    { +        PNOR_FLAG      = 0x01, +        MBOX_FLAG      = 0x02, +        ERRLDISP_FLAG  = 0x04, +    #ifdef CONFIG_CONSOLE_OUTPUT_ERRORDISPLAY +        ALL_FLAGS      = PNOR_FLAG | MBOX_FLAG | ERRLDISP_FLAG, +    #else +        ALL_FLAGS      = PNOR_FLAG | MBOX_FLAG, +    #endif +    }; + +    // List of messages errl manager needs to handle +    // The unint8_t is a bit field to indiciate what needs to be done +    std::list<std::pair<errlHndl_t, uint8_t> > iv_errlList; + +    typedef std::list<std::pair<errlHndl_t, uint8_t> >::iterator ErrlListItr_t; + +    /** +     * @brief checks if the pnor flag is set +     * +     * @param[in]   i_pair - pair of errl and bitfield of flags +     * @return      True if PNOR flag is set +     * +     */ +    static bool _isPnorFlagSet(const std::pair<errlHndl_t, uint8_t> &i_pair) +    { +        return (i_pair.second & PNOR_FLAG); +    } + +    /** +     * @brief checks if the mbox flag is set +     * +     * @param[in]   i_pair - pair of errl and bitfield of flagst +     * @return      True if mbox flag is set +     * +     */ +    static bool _isMboxFlagSet(const std::pair<errlHndl_t, uint8_t> &i_pair) +    { +        return (i_pair.second & MBOX_FLAG); +    } + +    /** +     * @brief checks if the errldisp flag is set +     * +     * @param[in]   i_pair - pair of errl and bitfield of flags +     * @return      True if errldisp flag is set +     * +     */ +    static bool _isErrlDispFlagSet(const std::pair<errlHndl_t, uint8_t> &i_pair) +    { +        return (i_pair.second & ERRLDISP_FLAG); +    } + +    /** +     * @brief clears the pnor flag, indicating complete +     * +     * @param[in/out]   io_pair - pair of errl and bitfield of flags +     * @return          NA +     * +     */ +    static void _clearPnorFlag(std::pair<errlHndl_t, uint8_t> &io_pair) +    { +        io_pair.second &= ~PNOR_FLAG; +    } + +    /** +     * @brief clears the mbox flag, indicating complete +     * +     * @param[in/out]   io_pair - pair of errl and bitfield of flags +     * @return          NA +     * +     */ +    static void _clearMboxFlag(std::pair<errlHndl_t, uint8_t> &io_pair) +    { +        io_pair.second &= ~MBOX_FLAG; +    } + +    /** +     * @brief clears the errldisp flag, indicating complete +     * +     * @param[in/out]   io_pair - pair of errl and bitfield of flags +     * @return          NA +     * +     */ +    static void _clearErrlDispFlag(std::pair<errlHndl_t, uint8_t> &io_pair) +    { +        io_pair.second &= ~ERRLDISP_FLAG; +    } + +    /** +     * @brief Checks if all flags are cleared for a errlhndl. +     *        If so deletes and NULLs the errl and removes from errl list. +     *        It then updates the iterator accordingly, done in this function +     *        to properly handle when a list.erase() happens +     * +     * @param[in/out]   io_it - iterator for the iv_errlList +     * @return          True if an erase occurred, otherwise false +     * +     */ +    bool _updateErrlListIter(std::list< std::pair<errlHndl_t, uint8_t> > +                                          ::iterator & io_it); +  };  } // End namespace diff --git a/src/include/usr/errldisplay/errldisplay.H b/src/include/usr/errldisplay/errldisplay.H new file mode 100644 index 000000000..fdd67ea58 --- /dev/null +++ b/src/include/usr/errldisplay/errldisplay.H @@ -0,0 +1,162 @@ +/* IBM_PROLOG_BEGIN_TAG                                                   */ +/* This is an automatically generated prolog.                             */ +/*                                                                        */ +/* $Source: src/include/usr/errldisplay/errldisplay.H $                   */ +/*                                                                        */ +/* OpenPOWER HostBoot Project                                             */ +/*                                                                        */ +/* Contributors Listed Below - COPYRIGHT 2013,2014                        */ +/* [+] Google Inc.                                                        */ +/* [+] International Business Machines Corp.                              */ +/*                                                                        */ +/*                                                                        */ +/* Licensed under the Apache License, Version 2.0 (the "License");        */ +/* you may not use this file except in compliance with the License.       */ +/* You may obtain a copy of the License at                                */ +/*                                                                        */ +/*     http://www.apache.org/licenses/LICENSE-2.0                         */ +/*                                                                        */ +/* Unless required by applicable law or agreed to in writing, software    */ +/* distributed under the License is distributed on an "AS IS" BASIS,      */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */ +/* implied. See the License for the specific language governing           */ +/* permissions and limitations under the License.                         */ +/*                                                                        */ +/* IBM_PROLOG_END_TAG                                                     */ +#ifndef ERRLDISPLAY_H +#define ERRLDISPLAY_H +/** + *  @file src/include/usr/errldisplay/errldisplay.H + * + *  @brief  Error Log display for Host Boot environment + * + */ + +/*****************************************************************************/ +// I n c l u d e s +/*****************************************************************************/ +#include <config.h> +#include <errl/errlentry.H> + +namespace ERRORLOGDISPLAY +{ + +/*****************************************************************************/ +// Forward class declarations +/*****************************************************************************/ + +class ErrLogDisplay; + +/** + *  @brief Returns a reference to the error log display singleton + * + *  @return Reference to the error log display + */ +ErrLogDisplay& errLogDisplay(); + +/** + *  @brief  Error log display module + *  This class provides a log dump function for host boot. + */ +class ErrLogDisplay +{ + +public: + +    /** +     * @struct errLogInfo +     * +     * Structure that holds human-readable strings describing errors +     */ +    struct errLogInfo +    { +        uint8_t moduleId; +        uint16_t reasonCode; +        const char * descriptString; +        const char * moduleName; +        const char * reasonString; +        const char * userData1String; +        const char * userData2String; +    }; + +    /** +     * @struct compTableInfo +     * +     * Structure that holds human readable strings for component IDs. +     */ +    struct compTableInfo +    { +        const compId_t value; +        const char * name; +    }; + +    // Sort function to compare errLogInfo structs +    static bool errorLogInfoCompare(const errLogInfo e1, const errLogInfo e2) +    { +        if (e1.moduleId == e2.moduleId) +        { +            return (e1.reasonCode < e2.reasonCode); +        } +        return (e1.moduleId < e2.moduleId); +    } + +    // Sort function to compare compTableInfo structs +    static bool compTableCompare(const compTableInfo c1, const compTableInfo c2) +    { +        return (c1.value < c2.value); +    } + +    /** +     *  @brief Display a human-readable error log entry. +     * +     *  @param[in] i_err                Error log handle to be displayed +     *  @param[in] i_committerComp      The id of the component that is +     *                                  committing this error log entry +     * +     *  @return None +     */ +    static void msgDisplay (const errlHndl_t &i_err, compId_t i_committerComp); + +    /** +     *  @brief Initialization for the error log display function. +     *  This registers with the core error logging to provide human-readable +     *  output for errors. +     */ +    errlHndl_t init(); + +private: + +    // Auto-generated data tables that hold error information. +    static errLogInfo errorInfo []; +    static uint16_t errorInfoTableSize; +    static compTableInfo compTable []; +    static uint16_t compTableSize; + +    /** +     * @brief Find the error log info struture that corresponds to the given +     * module ID & reason code. +     * +     * @param[in] moduleId    The id of the module which errored. +     * @param[in] reasonCode  The reason of the error. +     * +     * @return the error log info stucture that matches the module/reason code. +     * or NULL, if there is no structure found. +     */ +    static const errLogInfo* findErrLogInfo (uint8_t i_moduleId, +                                             uint16_t i_reasonCode); + +    /** +     * @brief Find the component name that corresponds to the given ID. +     * +     * @param[in] compId     The id of the component to be identified. +     * +     * @return a string with the name of the component, or "unknown" if the +     * module name is not found. +     */ +    static const char * findComponentName (compId_t i_compId); + +}; + +} // End namespace + +#endif //ERRLDISPLAY_H diff --git a/src/makefile b/src/makefile index 3dacfc1ba..f33622541 100644 --- a/src/makefile +++ b/src/makefile @@ -162,6 +162,7 @@ EXTENDED_MODULES += sbe  EXTENDED_MODULES += proc_hwreconfig  EXTENDED_MODULES += $(if $(CONFIG_GPIODD),gpio,)  EXTENDED_MODULES += $(if $(CONFIG_CONSOLE),console) +EXTENDED_MODULES += $(if $(CONFIG_CONSOLE_OUTPUT_ERRORDISPLAY),errldisplay)  EXTENDED_MODULES += $(if $(CONFIG_SET_NOMINAL_PSTATE),pstates)  TESTCASE_MODULES += cxxtest diff --git a/src/usr/errl/errlmanager.C b/src/usr/errl/errlmanager.C index 14a58b05f..0da331a44 100644 --- a/src/usr/errl/errlmanager.C +++ b/src/usr/errl/errlmanager.C @@ -6,6 +6,7 @@  /* OpenPOWER HostBoot Project                                             */  /*                                                                        */  /* Contributors Listed Below - COPYRIGHT 2011,2014                        */ +/* [+] Google Inc.                                                        */  /* [+] International Business Machines Corp.                              */  /*                                                                        */  /*                                                                        */ @@ -46,6 +47,10 @@  #include <pnor/pnorif.H>  #include <sys/mm.h>  #include <intr/interrupt.H> +#include <errldisplay/errldisplay.H> +#include <console/consoleif.H> +#include <config.h> +#include <functional>  namespace ERRORLOG  { @@ -87,6 +92,13 @@ const uint32_t PNOR_ERROR_LENGTH = 4096;  const uint32_t EMPTY_ERRLOG_IN_PNOR = 0xFFFFFFFF;  const uint32_t FIRST_BYTE_ERRLOG = 0xF0000000; +// Comparator function to check if a eid and a plid are equal +bool compareEidToPlid(const uint32_t i_plid, +                      const std::pair<errlHndl_t, uint8_t> i_pair) +{ +    return (i_pair.first->eid() == i_plid); +} +  class AtLoadFunctions  {      public: @@ -109,7 +121,8 @@ ErrlManager::ErrlManager() :      iv_pnorOpenSlot(0),      iv_isSpBaseServices(true),  // queue msgs for fsp until we find we shouldnt      iv_isMboxEnabled(false),    // but mbox isn't ready yet.. -    iv_nonInfoCommitted(false) +    iv_nonInfoCommitted(false), +    iv_isErrlDisplayEnabled(false)  {      TRACFCOMP( g_trac_errl, ENTER_MRK "ErrlManager::ErrlManager constructor" ); @@ -258,15 +271,15 @@ void ErrlManager::errlogMsgHndlr ()                      {                          iv_isSpBaseServices = false; -                        // if there are queued msgs, delete them -                        while (!iv_errlToSend.empty()) +                        // if there are queued msgs, delete the errors that +                        // have been fully processed +                        ErrlListItr_t it = iv_errlList.begin(); +                        while(it != iv_errlList.end())                          { -                            msg_t * msg = iv_errlToSend.front(); -                            free( msg->extra_data ); -                            msg_free( msg ); -                            // delete from the list -                            iv_errlToSend.pop_front(); -                        } // while items on iv_errlToSend list +                            // Mark MBOX processing complete +                            _clearMboxFlag(*it); +                            _updateErrlListIter(it); +                        }                      }                      //We are done with the msg @@ -313,38 +326,29 @@ void ErrlManager::errlogMsgHndlr ()                          // if error(s) came in before MBOX was ready,                          // the msg(s) would be on this list. send it now. -                        while (!iv_errlToSend.empty()) +                        ErrlListItr_t it = iv_errlList.begin(); +                        while(it != iv_errlList.end())                          { -                            msg_t * msg = iv_errlToSend.front(); - -                            l_err = MBOX::send( MBOX::FSP_ERROR_MSGQ, msg ); -                            if( l_err ) +                            // Check if MBOX processing is needed +                            if (_isMboxFlagSet(*it))                              { -                               TRACFCOMP(g_trac_errl, ERR_MRK "Failed sending error log to FSP"); - -                               //Free the extra data due to the error -                               free( msg->extra_data ); -                               msg_free( msg ); - -                               delete l_err; -                               l_err = NULL; +                                // Mark MBOX processing complete +                                sendErrLogToMbox(it->first); +                                _clearMboxFlag(*it);                              } - -                            // delete from the list -                            iv_errlToSend.pop_front(); -                        } // while items on list +                            _updateErrlListIter(it); +                        }                      }                      else                      { -                        // if there are queued msgs, delete them -                        while (!iv_errlToSend.empty()) +                        // Delete errors that have been completely processed +                        ErrlListItr_t it = iv_errlList.begin(); +                        while(it != iv_errlList.end())                          { -                            msg_t * msg = iv_errlToSend.front(); -                            free( msg->extra_data ); -                            msg_free( msg ); -                            // delete from the list -                            iv_errlToSend.pop_front(); -                        } // while items on iv_errlToSend list +                            // Mark MBOX processing complete +                            _clearMboxFlag(*it); +                            _updateErrlListIter(it); +                        }                      }                      //We are done with the msg @@ -353,9 +357,37 @@ void ErrlManager::errlogMsgHndlr ()                      // go back and wait for a next msg                      break;                  } +            case ERRLOG_ACCESS_ERRLDISP_TYPE: +                { +#ifdef CONFIG_CONSOLE_OUTPUT_ERRORDISPLAY +                    // Errldisplay now ready +                    iv_isErrlDisplayEnabled = true; + +                    CONSOLE::displayf("ERRL", +                        "Dumping errors reported prior to registration\n"); + +                    // Display errlogs to errldisplay +                    ErrlListItr_t it = iv_errlList.begin(); +                    while(it != iv_errlList.end()) +                    { +                        // Check if ERRLDISP processing is needed +                        if (_isErrlDispFlagSet(*it)) +                        { +                            ERRORLOGDISPLAY::errLogDisplay().msgDisplay +                                        (it->first, +                                        ((it->first->reasonCode()) & 0xFF00)); +                            // Mark ERRLDISP processing complete +                            _clearErrlDispFlag(*it); +                        } +                        _updateErrlListIter(it); +                    } +#endif +                    //We are done with the msg +                    msg_free(theMsg); +                }              case ERRLOG_NEEDS_TO_BE_COMMITTED_TYPE:                  { -                    //Extract error log handle from the message. We need the +                    // Extract error log handle from the message. We need the                      // error log handle to pass along to saveErrLogEntry and                      // sendErrLogToMbox                      errlHndl_t l_err = (errlHndl_t) theMsg->extra_data; @@ -363,25 +395,47 @@ void ErrlManager::errlogMsgHndlr ()                      //Ask the ErrlEntry to assign commit component, commit time                      l_err->commit( (compId_t) theMsg->data[0] ); +                    // Pair with all flags set to add to the errlList +                    std::pair<errlHndl_t, uint8_t> l_pair(l_err, ALL_FLAGS); + +                    // Display errl to errldisplay +#ifdef CONFIG_CONSOLE_OUTPUT_ERRORDISPLAY +                    if (iv_isErrlDisplayEnabled) +                    { +                        ERRORLOGDISPLAY::errLogDisplay().msgDisplay +                                            (l_err, +                                            ( (l_err->reasonCode()) & 0xFF00)); +                        // Mark ERRLDISP processing complete on this error +                        _clearErrlDispFlag(l_pair); +                    } +#endif                      //Save the error log to PNOR                      bool l_savedToPnor = saveErrLogToPnor(l_err); +                    // Check if we actually saved the msg to PNOR +                    if (l_savedToPnor) +                    { +                        // Mark PNOR processing complete on this error +                        _clearPnorFlag(l_pair); +                    } +  #ifdef STORE_ERRL_IN_L3                      //Write the error log to L3 memory                      //useful ONLY for the hb-errl tool                      saveErrLogEntry ( l_err );  #endif -                    //Try to send the error log if someone is there to receive -                    if (iv_isSpBaseServices) +                    // Try to send the error log if someone is there to receive +                    if (!iv_isSpBaseServices)                      { -                        msg_t *l_sentToMbox = sendErrLogToMbox ( l_err ); -                        if (l_sentToMbox != NULL) -                        { -                            // we were supposed to send it and couldn't; -                            // save it on the queue. -                            iv_errlToSend.push_back(l_sentToMbox); -                        } +                        // Mark MBOX processing complete on this error +                        _clearMboxFlag(l_pair); +                    } +                    else if (iv_isSpBaseServices && iv_isMboxEnabled) +                    { +                        sendErrLogToMbox(l_err); +                        // Mark MBOX processing complete on this error +                        _clearMboxFlag(l_pair);                      }                      //Ask the ErrlEntry to process any callouts @@ -400,17 +454,16 @@ void ErrlManager::errlogMsgHndlr ()                                  INFO_MRK"shutdown in progress" );                      } -                    // check if we actually saved the msg to PNOR -                    if (l_savedToPnor) +                    // If l_errl has not been fully proccessed delete it +                    // otherwise add to list +                    if (l_pair.second == 0)                      { -                        //done with the error log handle so delete it.                          delete l_err;                          l_err = NULL;                      }                      else -                    {   // save didn't work - push into a list to do when -                        //  the next ACK gets processed. -                        iv_errlToSave.push_back(l_err); +                    { +                        iv_errlList.push_back(l_pair);                      }                      //We are done with the msg @@ -427,53 +480,43 @@ void ErrlManager::errlogMsgHndlr ()                      TRACFCOMP( g_trac_errl, INFO_MRK"ack: %.8x", l_tmpPlid);                      bool didAck = ackErrLogInPnor(l_tmpPlid); -                      if (!didAck)                      {                          // couldn't find that errlog in PNOR, look in our -                        // ToSave list - maybe it's there waiting -                        for (std::list<errlHndl_t>::iterator -                            it = iv_errlToSave.begin(); -                            it != iv_errlToSave.end(); -                            it++) +                        // errlMsgList - maybe it's there waiting +                        ErrlListItr_t it = std::find_if(iv_errlList.begin(), +                                        iv_errlList.end(), +                                        std::bind1st(ptr_fun(&compareEidToPlid) +                                                             ,l_tmpPlid)); +                        // Check if such errl was found +                        if (it != iv_errlList.end())                          { -                            errlHndl_t l_err = *it; -                            if (l_err->eid() == l_tmpPlid) -                            { -                                // we found it -                                // done with the error log handle so delete it. -                                delete l_err; -                                l_err = NULL; - -                                // delete from the list -                                iv_errlToSave.erase(it); - -                                // break out of the for loop - we're done -                                break; -                            } -                        } // for +                            // We found the errlog +                            // Mark PNOR processing complete +                            _clearPnorFlag(*it); +                            _updateErrlListIter(it); +                        }                      }                      msg_free(theMsg); -                    if (!iv_errlToSave.empty()) -                    { -                        //we didn't have room before in PNOR to save an -                        // error log, so try now since we just ACKed one. -                        errlHndl_t l_err = iv_errlToSave.front(); +                    // We didn't have room before in PNOR to save an +                    // error log, so try now since we just ACKed one. +                    ErrlListItr_t it = std::find_if(iv_errlList.begin(), +                                                    iv_errlList.end(), +                                             _isPnorFlagSet); -                        bool l_savedToPnor = saveErrLogToPnor(l_err); +                    // Check if such errl was found +                    if (it != iv_errlList.end()) +                    { +                        bool l_savedToPnor = saveErrLogToPnor(it->first);                          // check if we actually saved the msg to PNOR                          if (l_savedToPnor) -                        {   // if so, we're done - clean up - -                            //done with the error log handle so delete it. -                            delete l_err; -                            l_err = NULL; - -                            // delete from the list -                            iv_errlToSave.pop_front(); +                        { +                            // Mark PNOR processing complete +                            _clearPnorFlag(*it); +                            _updateErrlListIter(it);                          }                          // else, still couldn't save it (for some reason) so                          // it's still on the list. @@ -513,7 +556,7 @@ void ErrlManager::errlogMsgHndlr ()  ///////////////////////////////////////////////////////////////////////////////  // ErrlManager::sendErrLogToMbox()  /////////////////////////////////////////////////////////////////////////////// -msg_t *ErrlManager::sendErrLogToMbox ( errlHndl_t& io_err ) +void ErrlManager::sendErrLogToMbox ( errlHndl_t& io_err )  {      msg_t *msg = NULL; @@ -532,50 +575,35 @@ msg_t *ErrlManager::sendErrLogToMbox ( errlHndl_t& io_err )          msg->data[0] = io_err->eid();          msg->data[1] = l_msgSize; -        void * temp_buff = NULL; -        if( iv_isMboxEnabled ) -        { -            temp_buff = MBOX::allocate( l_msgSize ); -        } -        else -        { -            temp_buff = malloc( l_msgSize ); -        } +        void * temp_buff = MBOX::allocate( l_msgSize );          io_err->flatten ( temp_buff, l_msgSize );          msg->extra_data = temp_buff;          TRACDCOMP( g_trac_errl, INFO_MRK"Send msg to FSP for errlogId %.8x",                                                                 io_err->eid() ); - -        if (iv_isMboxEnabled) +        errlHndl_t l_err = MBOX::send( MBOX::FSP_ERROR_MSGQ, msg ); +        if( !l_err )          { -            errlHndl_t l_err = MBOX::send( MBOX::FSP_ERROR_MSGQ, msg ); -            if( !l_err ) -            { -                // clear this - we're done with the message; -                // the receiver will free the storage when it's done -                msg = NULL; -            } -            else -            { -               TRACFCOMP(g_trac_errl, ERR_MRK"Failed sending error log to FSP"); +            // clear this - we're done with the message; +            // the receiver will free the storage when it's done +            msg = NULL; +        } +        else +        { +           TRACFCOMP(g_trac_errl, ERR_MRK"Failed sending error log to FSP"); -               //Free the extra data due to the error -               MBOX::deallocate( msg->extra_data ); -               msg_free( msg ); -               msg = NULL; +           //Free the extra data due to the error +           MBOX::deallocate( msg->extra_data ); +           msg_free( msg ); +           msg = NULL; -               delete l_err; -               l_err = NULL; -            } +           delete l_err; +           l_err = NULL;          } -        // else, we created the msg, but couldn't send it - return it so that -        // it can be saved and sent later when the MBOX is up.      } while (0); -    TRACFCOMP( g_trac_errl, EXIT_MRK"sendErrLogToMbox() returning %p", msg); -    return msg; +    TRACFCOMP( g_trac_errl, EXIT_MRK"ErrlManager::sendErrLogToMbox" );  } // sendErrLogToMbox  /////////////////////////////////////////////////////////////////////////////// @@ -695,7 +723,6 @@ void errlCommit(errlHndl_t& io_err, compId_t i_committerComp )  }  /////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////  // Global function (not a method on an object) to commit the error log.  void ErrlManager::errlResourceReady(errlManagerNeeds i_needs)  { @@ -721,6 +748,9 @@ void ErrlManager::sendResourcesMsg(errlManagerNeeds i_needs)          case MBOX:              msg->type = ERRORLOG::ErrlManager::ERRLOG_ACCESS_MBOX_TYPE;              break; +        case ERRLDISP: +            msg->type = ERRORLOG::ErrlManager::ERRLOG_ACCESS_ERRLDISP_TYPE; +            break;          default:          {              TRACFCOMP( g_trac_errl, ERR_MRK "bad msg!!"); @@ -797,30 +827,22 @@ void ErrlManager::sendErrlogToMessageQueue ( errlHndl_t& io_err,  ///////////////////////////////////////////////////////////////////////////////  void ErrlManager::errlogShutdown()  { -    // if there are errorlogs that didn't get sent via the MBOX to FSP, -    //  trace them and clean up -    while (!iv_errlToSend.empty()) +    // if there are errorlogs that didn't get fully processed, trace them +    // and clean up +    while (!iv_errlList.empty())      { -        msg_t * msg = iv_errlToSend.front(); -        TRACDCOMP(g_trac_errl, INFO_MRK "Failed to send to FSP: eid %.8x", -                msg->data[0]); -        free( msg->extra_data ); -        msg_free( msg ); -        // delete from the list -        iv_errlToSend.pop_front(); -    } // while items on iv_errlToSend list +        // Get errl and its flags +        std::pair<errlHndl_t, uint8_t> l_pair = iv_errlList.front(); +        // If still true that means it was not processed -    // if there are errorlogs that didn't get stored in PNOR, -    //  trace them and clean up -    while (!iv_errlToSave.empty()) -    { -        errlHndl_t l_err = iv_errlToSave.front(); -        TRACFCOMP(g_trac_errl, ERR_MRK "Failed to store to PNOR: eid %.8x", -                l_err->eid()); -        delete l_err; +        TRACFCOMP(g_trac_errl, INFO_MRK "Failed to fully process Errl(eid %.8x) - Errl Flags Bitfield = 0x%X", +                    l_pair.second); + +        delete l_pair.first; +        l_pair.first = NULL;          // delete from the list -        iv_errlToSave.pop_front(); -    } // while items on iv_errlToSave list +        iv_errlList.pop_front(); +    } // while items on iv_errlList list      // Ensure that all the error logs are pushed out to PNOR      // prior to the PNOR resource provider shutting down. @@ -928,32 +950,34 @@ void ErrlManager::setupPnorInfo()          // if error(s) came in before PNOR was ready,          // the error log(s) would be on this list. save now. -        while (!iv_errlToSave.empty()) +        ErrlListItr_t it = iv_errlList.begin(); +        while(it != iv_errlList.end())          { -            errlHndl_t l_err = iv_errlToSave.front(); - -            //ACK it if no one is there to receive -            bool l_savedToPnor = saveErrLogToPnor(l_err); - -            // check if we actually saved the msg to PNOR -            if (l_savedToPnor) -            {   // if so, we're done - clean up - -                //done with the error log handle so delete it. -                delete l_err; -                l_err = NULL; +            // Check if PNOR processing is needed +            if (_isPnorFlagSet(*it)) +            { +                //ACK it if no one is there to receive +                bool l_savedToPnor = saveErrLogToPnor(it->first); -                // delete from the list -                iv_errlToSave.pop_front(); +                // check if we actually saved the msg to PNOR +                if (l_savedToPnor) +                { +                    // Mark PNOR processing complete +                    _clearPnorFlag(*it); +                    _updateErrlListIter(it); +                } +                else +                { +                    // still couldn't save it (PNOR maybe full) so +                    // it's still on the list. +                    break; // get out of this while loop. +                }              }              else              { -                // still couldn't save it (PNOR maybe full) so -                // it's still on the list. -                break; // get out of this while loop. +                ++it;              } -        } // while entries on list - +        }      } while (0);      TRACFCOMP( g_trac_errl, EXIT_MRK"setupPnorInfo"); @@ -985,8 +1009,8 @@ bool ErrlManager::incrementPnorOpenSlot()  ///////////////////////////////////////////////////////////////////////////////  bool ErrlManager::saveErrLogToPnor( errlHndl_t& io_err)  { -    TRACFCOMP( g_trac_errl, ENTER_MRK"saveErrLogToPnor eid=%.8x", io_err->eid());      bool rc = false; +    TRACFCOMP( g_trac_errl, ENTER_MRK"saveErrLogToPnor eid=%.8x", io_err->eid());      // actually, if it's an INFORMATIONAL log, we don't want to waste the write      // cycles, so we'll just 'say' that we saved it and go on. @@ -1041,9 +1065,8 @@ bool ErrlManager::saveErrLogToPnor( errlHndl_t& io_err)          }          // else no open slot - return false      } -      TRACFCOMP( g_trac_errl, EXIT_MRK"saveErrLogToPnor returning %s", -            rc ?  "true" : "false"); +        rc ? "true" : "false");      return rc;  } // saveErrLogToPnor @@ -1155,4 +1178,23 @@ void ErrlManager::setACKInFlattened(uint32_t i_position)      return;  } +bool ErrlManager::_updateErrlListIter(ErrlListItr_t & io_it) +{ +    bool l_removed = false; +    // Delete if this error has been fully processed (flags cleared) +    if (io_it->second == 0) +    { +        // Delete errl +        delete io_it->first; +        io_it->first = NULL; +        io_it = iv_errlList.erase(io_it); +        l_removed = true; +    } +    else +    { +        ++io_it; +    } +    return l_removed; +} +  } // End namespace diff --git a/src/usr/errl/parser/genErrlParsers.pl b/src/usr/errl/parser/genErrlParsers.pl index 626b6b763..7fb516683 100755 --- a/src/usr/errl/parser/genErrlParsers.pl +++ b/src/usr/errl/parser/genErrlParsers.pl @@ -7,6 +7,7 @@  # OpenPOWER HostBoot Project  #  # Contributors Listed Below - COPYRIGHT 2013,2014 +# [+] Google Inc.  # [+] International Business Machines Corp.  #  # @@ -442,6 +443,7 @@ close(OFILE);  my %compValueToParseHash;  my %rcModValuesUsed;  my %srcList; +my %displayDataEntries;  foreach my $file (@filesToParse)  { @@ -479,6 +481,7 @@ foreach my $file (@filesToParse)              my $rc = "";              my $rcValue = "";              my @userData; +            my @userDataTextOnly;              my $desc = "";              my $cdesc = ""; @@ -607,6 +610,7 @@ foreach my $file (@filesToParse)                      my $udString = "\"$udDesc\", \"$udText\"";                      push(@userData, $udString); +                    push(@userDataTextOnly, $udText);                  }                  elsif ($line =~ /\@devdesc\s+(\S+.*)/i)                  { @@ -740,12 +744,26 @@ foreach my $file (@filesToParse)              }              $parserCode .= "        break;\n\n"; +            # Create the data entry code for this error +            my $dataEntryCode = "    {\n" +                              . "     0x$modIdValue,   // Module Id\n" +                              . "     0x$rcValue,  // ReasonCode\n" +                              . "     \"$desc\",\n" +                              . "     \"$modId\",\n" +                              . "     \"$rc\",\n" +                              . "     \"$userDataTextOnly[0]\",\n" +                              . "     \"$userDataTextOnly[1]\"\n" +                              . "    },\n\n"; +              # The component value is the first two characters of the 4 character rc              my $compValue = $rcValue;              $compValue =~ s/..$//;              # Add the parser code to compValueToParseHash              $compValueToParseHash{$compValue} .= $parserCode; + +            # Add the data entry code to displayDataEntries +            $displayDataEntries{$modIdValue}{$rcValue} = $dataEntryCode;          }      } @@ -1028,6 +1046,52 @@ print OFILE "\n\n.include<\${RULES_MK}>\n";  close(OFILE);  #------------------------------------------------------------------------------ +# Generate the errldisplaydata.C file that contains the set of Hostboot +# component IDs and detailed error data. +# Note: This file is placed one directory up from the other generated files +#       because this is actually part of hostboot. +#------------------------------------------------------------------------------ +$outputFileName = $outputDir . "/../errldisplaydata.C"; +open(OFILE, ">", $outputFileName) or die("Cannot open: $outputFileName: $!"); + +print OFILE "/*\n"; +print OFILE " * Automatically generated by Hostboot's $0\n"; +print OFILE " * Do not modify this file in the hostboot tree, it is automatically\n"; +print OFILE " * generated every build.\n"; +print OFILE " *\n"; +print OFILE " * TimeStamp:   $timestamp\n"; +print OFILE " * Image Id:    $imageId\n"; +print OFILE " *\n"; +print OFILE " */\n\n"; +print OFILE "#include <errldisplay/errldisplay.H>\n"; +print OFILE "#include <stdlib.h>\n\n"; +print OFILE "namespace ERRORLOGDISPLAY\n{\n\n"; +print OFILE "// Error Info Table\n"; +print OFILE "ErrLogDisplay::errLogInfo ErrLogDisplay::errorInfo [] = {\n"; +foreach my $modID (sort keys %displayDataEntries) +{ +    foreach my $rc (sort keys %{$displayDataEntries{$modID}}) +    { +        print OFILE $displayDataEntries{$modID}{$rc}; +    } +} + +print OFILE "};\n"; +print OFILE "uint16_t ErrLogDisplay::errorInfoTableSize = sizeof(errorInfo) / sizeof(errorInfo[0]);\n\n"; +print OFILE "\n\n// Component Id Table\n"; +print OFILE "#include <hbotcompid.H>\n"; +print OFILE "ErrLogDisplay::compTableInfo ErrLogDisplay::compTable [] = {\n"; +foreach my $key (sort keys %compIdToValueHash) +{ +    $key = substr($key,0,length($key)-3); +    print OFILE "    {" . $key . "_ID, " . $key . "_NAME},\n"; +} +print OFILE "};\n"; +print OFILE "uint16_t ErrLogDisplay::compTableSize = sizeof(compTable) / sizeof(compTable[0]);\n\n"; +print OFILE "} // End Namespace\n"; +close(OFILE); + +#------------------------------------------------------------------------------  # Subroutine that prints the usage  #------------------------------------------------------------------------------  sub usage diff --git a/src/usr/errl/parser/makefile b/src/usr/errl/parser/makefile index e008e6974..05a3ab0fa 100644 --- a/src/usr/errl/parser/makefile +++ b/src/usr/errl/parser/makefile @@ -6,6 +6,7 @@  # OpenPOWER HostBoot Project  #  # Contributors Listed Below - COPYRIGHT 2011,2014 +# [+] Google Inc.  # [+] International Business Machines Corp.  #  # @@ -96,6 +97,7 @@ clean:  	rm -f ${GENDIR}/comps.C  	rm -f ${IMGDIR}/errlparser  	rm -fr ${OBJDIR} +	rm -f ${GENDIR}/errldisplaydata.C  debug:  	ls -l 	${GENDIR} diff --git a/src/usr/errldisplay/errldisplay.C b/src/usr/errldisplay/errldisplay.C new file mode 100644 index 000000000..f3a80b839 --- /dev/null +++ b/src/usr/errldisplay/errldisplay.C @@ -0,0 +1,195 @@ +/* IBM_PROLOG_BEGIN_TAG                                                   */ +/* This is an automatically generated prolog.                             */ +/*                                                                        */ +/* $Source: src/usr/errldisplay/errldisplay.C $                           */ +/*                                                                        */ +/* OpenPOWER HostBoot Project                                             */ +/*                                                                        */ +/* Contributors Listed Below - COPYRIGHT 2013,2014                        */ +/* [+] Google Inc.                                                        */ +/* [+] International Business Machines Corp.                              */ +/*                                                                        */ +/*                                                                        */ +/* Licensed under the Apache License, Version 2.0 (the "License");        */ +/* you may not use this file except in compliance with the License.       */ +/* You may obtain a copy of the License at                                */ +/*                                                                        */ +/*     http://www.apache.org/licenses/LICENSE-2.0                         */ +/*                                                                        */ +/* Unless required by applicable law or agreed to in writing, software    */ +/* distributed under the License is distributed on an "AS IS" BASIS,      */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */ +/* implied. See the License for the specific language governing           */ +/* permissions and limitations under the License.                         */ +/*                                                                        */ +/* IBM_PROLOG_END_TAG                                                     */ +/** + *  @file /src/usr/errl/display/errldisplay.C + * + *  @brief Implementation of ErrlDisplay class + *         This will display human-readable dumps of error log entries. + * + *  The strings displayed are automatically extracted from source code by + *  the script ../errl/parser/genErrlParsers.pl + * + *  The base image is limited to 512K, and inclusion of the error strings + *  in the base make it grow beyond that limit, so the text and display + *  functions are put into the extended image. + * + *  The errl module in the base image will provide an interface for the + *  display functions to register with it. + *  When an errl is generated, the base image will see if a display function + *  has been registered.  If so, then it will be called to display the error. + *  If not, then the base image will display the raw error data and save the + *  error information into a list. + *  When the display function does register itself, the errl module in the + *  base image will pretty-print all of the pending errors from the list + *  it generated before that point. + */ + +/*****************************************************************************/ +// I n c l u d e s +/*****************************************************************************/ +#include <trace/interface.H> +#include <errl/errlmanager.H> +#include <errl/errlentry.H> +#include <errldisplay/errldisplay.H> +#include <stdlib.h> +#include <string.h> +#include <initservice/taskargs.H> +#include <algorithm> +#include <console/consoleif.H> + +namespace ERRORLOGDISPLAY +{ + +// Trace definition +trace_desc_t* g_trac_errldisp = NULL; +TRAC_INIT(&g_trac_errldisp, "ERRLDISP", KILOBYTE, TRACE::BUFFER_SLOW); + +/** + * @brief Default error log to display when we can't find one in the errorInfo + *        table. + * + * The data tables and size variables + *   static errLogInfo errorInfo [] + *   static compTableInfo compTable [] + *   static uint16_t errorInfoTableSize + *   static uint16_t compTableSize + * are automatically generated by the ../errl/parser/genErrlTable.pl script + * and placed in the file $GENDIR/errldisplaydata.C + */ +static const ErrLogDisplay::errLogInfo unknownErrorInfo = { +    0,           // Module Id +    0,           // Reason Code +    "<none>",    // Description +    "unknown",   // Module Name +    "unknown",   // Reason +    "unknown",   // User Data 1 string +    "unknown"    // User Data 2 string +}; + + +ErrLogDisplay& errLogDisplay() +{ +    return Singleton<ErrLogDisplay>::instance(); +} + +const ErrLogDisplay::errLogInfo* ErrLogDisplay::findErrLogInfo ( +                                    uint8_t i_moduleId, uint16_t i_reasonCode) +{ +    // Create local errLogInfo to search for +    struct ErrLogDisplay::errLogInfo l_errLogInfo = {i_moduleId,i_reasonCode, +                                                     NULL,NULL,NULL,NULL,NULL}; + +    errLogInfo* l_result = std::lower_bound(errorInfo, +                                            errorInfo + errorInfoTableSize, +                                            l_errLogInfo, +                                            ErrLogDisplay::errorLogInfoCompare); + +    // Check if the lower_bound found the correct result +    if ( (l_result != (errorInfo + errorInfoTableSize)) && +         (l_result->moduleId == i_moduleId) && +         (l_result->reasonCode == i_reasonCode) ) +    { +        return l_result; +    } + +    // Couldn't find it, so return the default unknown structure. +    return &unknownErrorInfo; +} + +const char * ErrLogDisplay::findComponentName (compId_t i_compId) +{ +    // Create local compTableInfo to search for +    struct ErrLogDisplay::compTableInfo l_compTableInfo = {i_compId, NULL}; + +    compTableInfo* l_result = std::lower_bound(compTable, +                                               compTable + compTableSize, +                                               l_compTableInfo, +                                               ErrLogDisplay::compTableCompare); + +    // Check if the lower_bound found the correct result +    if ( (l_result != (compTable + errorInfoTableSize)) && +         (l_result->value == i_compId) ) +    { +        return l_result->name; +    } +    return "unknown"; +} + +void ErrLogDisplay::msgDisplay (const errlHndl_t &i_err, +                                compId_t i_committerComp) +{ +    TRACFCOMP( g_trac_errldisp, ENTER_MRK "ErrLogDisplay::msgDisplay" ); + +    const ErrLogDisplay::errLogInfo* info = findErrLogInfo(i_err->moduleId(), +                                                           i_err->reasonCode()); + +    CONSOLE::displayf(NULL, +                      "================================================\n"); +    CONSOLE::displayf(NULL, "Error reported by %s (0x%04X)\n", +                      findComponentName(i_committerComp), i_committerComp); +    CONSOLE::displayf(NULL, "  %s\n", info->descriptString); +    CONSOLE::displayf(NULL, "  ModuleId   0x%02x %s\n", +                      i_err->moduleId(), info->moduleName); +    CONSOLE::displayf(NULL, "  ReasonCode 0x%04x %s\n", +                      i_err->reasonCode(), info->reasonString); +    CONSOLE::displayf(NULL, "  UserData1  %s : 0x%016lx\n", +                      info->userData1String, i_err->getUserData1()); +    CONSOLE::displayf(NULL, "  UserData2  %s : 0x%016lx\n", +                      info->userData2String, i_err->getUserData2()); + +    CONSOLE::flush(); + +    TRACFCOMP( g_trac_errldisp, EXIT_MRK "ErrLogDisplay::msgDisplay" ); +} + + +/** + * @brief This is the task entry point. It will register ErrlDisplay module with + *        the base image Errl module. + * + * @param[in/out] io_taskRetErrl    Errl module to register with ErrlDisplay + *                                  instance + * + * @return None + */ +static void errLogDisplayEntryPoint (errlHndl_t &io_taskRetErrl) +{ +    TRACFCOMP( g_trac_errldisp, ENTER_MRK "ErrLogDisplay::errLogDisplayEntryPoint" ); + +    io_taskRetErrl = Singleton<ErrLogDisplay>::instance().init(); + +    TRACFCOMP( g_trac_errldisp, EXIT_MRK "ErrLogDisplay::errLogDisplayEntryPoint" ); +} +TASK_ENTRY_MACRO( errLogDisplayEntryPoint ); + + +errlHndl_t ErrLogDisplay::init() +{ +    ERRORLOG::ErrlManager::errlResourceReady(ERRORLOG::ERRLDISP); +    return NULL; +} + +} // End namespace diff --git a/src/usr/errldisplay/makefile b/src/usr/errldisplay/makefile new file mode 100644 index 000000000..7c70f2bb5 --- /dev/null +++ b/src/usr/errldisplay/makefile @@ -0,0 +1,37 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/usr/errldisplay/makefile $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 2013,2014 +# [+] Google Inc. +# [+] International Business Machines Corp. +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +#     http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# IBM_PROLOG_END_TAG + +ROOTPATH = ../../.. +MODULE = errldisplay + +OBJS += errldisplay.o +OBJS += errldisplaydata.o + +include ${ROOTPATH}/config.mk + +# To find errldisplaydata.C - it is generated +# by ../errl/parser/genErrlParsers.pl +vpath %.C ${GENDIR} diff --git a/src/usr/initservice/extinitsvc/extinitsvctasks.H b/src/usr/initservice/extinitsvc/extinitsvctasks.H index 19fe70a84..9996bc994 100644 --- a/src/usr/initservice/extinitsvc/extinitsvctasks.H +++ b/src/usr/initservice/extinitsvc/extinitsvctasks.H @@ -120,6 +120,23 @@ const TaskInfo g_exttaskinfolist[]   =   {              }          }, +#ifdef CONFIG_CONSOLE_OUTPUT_ERRORDISPLAY +        /** +         * @brief Human readable error log display +         * Note: Because of dependencies, this must come after libmbox.so +         *       or hostboot will hang with an Inst Storage exception +         *       (the ErrlManager constructor tries to talk to MBOX.) +         */ +        { +            "liberrldisplay.so",                        // taskname +            NULL,                                       // no ptr to fnct +            { +                START_TASK,                             // task type +                EXT_IMAGE,                              // Extended Module +            } +        }, +#endif +          /**           * @brief Trace daemon           */ diff --git a/src/usr/makefile b/src/usr/makefile index 746868f18..02f622520 100644 --- a/src/usr/makefile +++ b/src/usr/makefile @@ -62,5 +62,6 @@ SUBDIRS += sbe.d  SUBDIRS += gpio.d  SUBDIRS += lpc.d  SUBDIRS += console.d +SUBDIRS += errldisplay.d  include ${ROOTPATH}/config.mk | 

