diff --git a/algo/CMakeLists.txt b/algo/CMakeLists.txt
index 59e4d431644146d57de67fd882d39bd328a301d5..fa94bdca04bc6461df3cd1655f82b67869a01330 100644
--- a/algo/CMakeLists.txt
+++ b/algo/CMakeLists.txt
@@ -109,6 +109,7 @@ set(SRCS
   detectors/tof/HitfinderChain.cxx
   detectors/tof/CalibratorChain.cxx
   detectors/tof/config/ReadoutPars_mCBM2022.cxx
+  detectors/tof/config/ReadoutPars_mCBM2024.cxx
   detectors/bmon/ReadoutConfig.cxx
   detectors/bmon/Unpack.cxx
   detectors/bmon/UnpackMS.cxx
diff --git a/algo/base/Options.cxx b/algo/base/Options.cxx
index fad88ed6193c9d1dd56278d8ac46c5283919e9a2..5c4f42813a387d5b658cbd0ada66a10cf3647e5c 100644
--- a/algo/base/Options.cxx
+++ b/algo/base/Options.cxx
@@ -82,6 +82,7 @@ Options::Options(int argc, char** argv)
     ("systems,s", po::value(&fDetectors)->multitoken()->default_value({Subsystem::STS, Subsystem::TOF, Subsystem::BMON, Subsystem::MUCH, Subsystem::RICH, Subsystem::TRD, Subsystem::TRD2D})->value_name("<detectors>"),
       "space seperated list of detectors to process (sts, mvd, ...)")
     ("child-id,c", po::value(&fChildId)->default_value("00")->value_name("<id>"), "online process id on node")
+    ("run-id,r", po::value(&fRunId)->default_value(2391)->value_name("<RunId>"), "Run ID, for now flesctl run index, later run start time")
     ("num-ts,n", po::value(&fNumTimeslices)->default_value(-1)->value_name("<num>"),
       "Stop after <num> timeslices (-1 = all)")
     ("skip-ts", po::value(&fSkipTimeslices)->default_value(0)->value_name("<num>"),
diff --git a/algo/base/Options.h b/algo/base/Options.h
index b4c0c7a39d9217bdaeda79dcf456e6cda9be7ea2..06eb0c2fac39f853a86b0ac4dc7a9a0c281e9926 100644
--- a/algo/base/Options.h
+++ b/algo/base/Options.h
@@ -43,6 +43,7 @@ namespace cbm::algo
       return fNumOMPThreads > 0 ? std::make_optional(fNumOMPThreads) : std::nullopt;
     }
     const std::string& ChildId() const { return fChildId; }
+    uint64_t RunId() const { return fRunId; }
     bool DumpArchive() const { return fDumpArchive; }
 
     const std::vector<Step>& Steps() const { return fRecoSteps; }
@@ -78,6 +79,7 @@ namespace cbm::algo
     bool fCompressArchive = false;
     std::vector<fles::Subsystem> fDetectors;
     std::string fChildId = "00";
+    uint64_t fRunId      = 2391;
   };
 
 }  // namespace cbm::algo
diff --git a/algo/detectors/tof/ReadoutConfig.cxx b/algo/detectors/tof/ReadoutConfig.cxx
index 6234bbead9771ee2ccaf5cdcbc52f33d06bc28b1..c5b8a599887e94176e315dee1a5ffac897c457c3 100644
--- a/algo/detectors/tof/ReadoutConfig.cxx
+++ b/algo/detectors/tof/ReadoutConfig.cxx
@@ -75,7 +75,8 @@ namespace cbm::algo::tof
 
       for (uint16_t elink = 0; elink < pars.NElinksPerComponent(); elink++) {
         fReadoutMap[equipment][elink].resize(pars.nChannelsPerAsic);
-        const uint32_t asicId = ElinkIdxToGet4Idx(elink, pars);
+        const uint32_t asicId =
+          pars.CheckInnerComp(equipment) ? ElinkIdxToGet4IdxInner(elink, pars) : ElinkIdxToGet4Idx(elink, pars);
 
         for (uint16_t channel = 0; channel < pars.nChannelsPerAsic; channel++) {
           const uint32_t febId     = (asicId / pars.nAsicsPerFeb);
@@ -98,8 +99,26 @@ namespace cbm::algo::tof
       return pars.elink2Asic[elink % pars.NElinksPerCrob()] + pars.NElinksPerCrob() * (elink / pars.NElinksPerCrob());
     }
     else {
-      throw FatalError("CbmMcbm2018TofPar::ElinkIdxToGet4Idx => Index out of bound, {} vs {}, returning crazy value!",
-                       elink, static_cast<uint32_t>(pars.NElinksPerComponent()));
+      throw FatalError("tof::ReadoutConfig::ElinkIdxToGet4Idx => Index out of bound, {} vs {}, stop there!", elink,
+                       static_cast<uint32_t>(pars.NElinksPerComponent()));
+    }
+  }
+
+  int32_t ReadoutConfig::ElinkIdxToGet4IdxInner(uint32_t elink, const config::ReadoutPars& pars)
+  {
+    if (0 == pars.elink2AsicInner.size()) {
+      throw FatalError("tof::ReadoutConfig::ElinkIdxToGet4IdxInner => map is empty, stop there, check your Config!");
+    }
+    else if (gdpbv100::kuChipIdMergedEpoch == elink) {
+      return elink;
+    }
+    else if (elink < pars.NElinksPerComponent()) {
+      return pars.elink2AsicInner[elink % pars.NElinksPerCrob()]
+             + pars.NElinksPerCrob() * (elink / pars.NElinksPerCrob());
+    }
+    else {
+      throw FatalError("tof::ReadoutConfig::ElinkIdxToGet4IdxInner => Index out of bound, {} vs {}, stop there!", elink,
+                       static_cast<uint32_t>(pars.NElinksPerComponent()));
     }
   }
   // -------------------------------------------------------------------------
@@ -125,9 +144,16 @@ namespace cbm::algo::tof
     uint32_t uNrOfChannels = uNrOfGet4 * pars.nChannelsPerAsic;
     fviRpcChUId.resize(uNrOfChannels);
 
+    uint32_t nbRobPerComp = 2;  // number of Gbtx per Gdpb (flim) for the final channel count check
+    if (pars.mcbmTof2024) {
+      // Hack for 2024 TOF mapping
+      nbRobPerComp = 1;
+    }
+
     uint32_t uCh = 0;
     for (uint32_t uGbtx = 0; uGbtx < pars.NCROBs(); ++uGbtx) {
-      uint32_t uCh0 = uCh;
+      uint32_t uCh0    = uCh;
+      uint32_t uGdpb   = uCh0 / (pars.nFebsPerComponent * pars.nAsicsPerFeb * pars.nChannelsPerAsic);
       const auto& crob = pars.crobs.at(uGbtx);
       switch (crob.rpcType) {
         case 2:  // intended fall-through
@@ -156,12 +182,22 @@ namespace cbm::algo::tof
         case 7: [[fallthrough]];
         case 9:  // Star2 boxes
         {
-          BuildChannelsUidMapStar2(uCh, crob);
+          if ((pars.eqIds[uGdpb] & 0xF000) == 0xB000) {
+            BuildChannelsUidMapStar2Inner(uCh, crob);
+          }
+          else {
+            BuildChannelsUidMapStar2(uCh, crob);
+          }
           break;
         }
         case 6:  // Buc box
         {
-          BuildChannelsUidMapBuc(uCh, crob);
+          if ((pars.eqIds[uGdpb] & 0xF000) == 0xB000) {
+            BuildChannelsUidMapStar2Inner(uCh, crob);
+          }
+          else {
+            BuildChannelsUidMapBuc(uCh, crob);
+          }
           break;
         }
         case 69: {
@@ -182,7 +218,7 @@ namespace cbm::algo::tof
           L_(error) << "Invalid Tof Type specifier for GBTx " << std::setw(2) << uGbtx << ": " << crob.rpcType;
         }
       }  // switch (crob.rpcType)
-      if (int32_t(uCh - uCh0) != pars.nFebsPerComponent * pars.nAsicsPerFeb * pars.nChannelsPerAsic / 2) {
+      if (int32_t(uCh - uCh0) != pars.nFebsPerComponent * pars.nAsicsPerFeb * pars.nChannelsPerAsic / nbRobPerComp) {
         throw FatalError("Tof mapping error for Gbtx {},  diff = {}, type {}", uGbtx, uCh - uCh0, crob.rpcType);
       }
     }  // for (UInt_t uGbtx = 0; uGbtx < numCrob; ++uGbtx)
@@ -339,6 +375,92 @@ namespace cbm::algo::tof
     }
   }
 
+  // -------------------------------------------------------------------------
+  void ReadoutConfig::BuildChannelsUidMapStar2Inner(uint32_t& uCh, const config::CROB& crob)
+  {
+    if (crob.rpcSide < 3) {
+      int32_t NrFeet = 2;
+      if (crob.rpcSide < 2) NrFeet = 1;
+      int32_t iFeet = 0;
+      for (; iFeet < NrFeet; iFeet++) {
+        for (int32_t iStr = 0; iStr < 32; iStr++) {
+          int32_t iStrMap  = iStr;
+          int32_t iRpcMap  = crob.nRPC;
+          int32_t iSideMap = crob.rpcSide;
+          if (crob.rpcSide == 2) {
+            if (iFeet == 0)
+              iSideMap = 0;
+            else
+              iSideMap = 1;
+          }
+          else {
+            if (crob.rpcSide == 3) {
+              if (iFeet == 0)
+                iSideMap = 1;
+              else
+                iSideMap = 0;
+            }
+          }
+          if (crob.rpcType != 6)
+            if (iSideMap == 0) iStrMap = 31 - iStr;
+
+          if (iSideMap > -1)
+            fviRpcChUId[uCh] = CbmTofAddress::GetUniqueAddress(crob.moduleId, iRpcMap, iStrMap, iSideMap, crob.rpcType);
+          else
+            fviRpcChUId[uCh] = 0;
+
+          uCh++;
+        }
+      }
+      while (iFeet < 2) {
+        for (int32_t iStr = 0; iStr < 32; iStr++) {
+          fviRpcChUId[uCh] = 0;
+          uCh++;
+        }
+        iFeet++;
+      }
+    }
+    else {
+      if (crob.rpcSide == 3) {
+        int iSideMap = -1;
+        int iStrMap  = -1;
+        int iRpcMap  = -1;
+        for (int32_t iFeet = 0; iFeet < 5; iFeet++) {
+          for (int32_t iStr = 0; iStr < 32; iStr++) {
+            switch (iFeet) {
+              case 0: iSideMap = -1; break;
+              case 1:
+                iRpcMap  = 0;
+                iStrMap  = iStr;
+                iSideMap = 0;
+                break;
+              case 2:
+                iRpcMap  = 0;
+                iStrMap  = iStr;
+                iSideMap = 1;
+                break;
+              case 3:
+                iRpcMap  = 1;
+                iStrMap  = iStr;
+                iSideMap = 0;
+                break;
+              case 4:
+                iRpcMap  = 1;
+                iStrMap  = iStr;
+                iSideMap = 1;
+                break;
+            }
+            if (iSideMap > -1)
+              fviRpcChUId[uCh] =
+                CbmTofAddress::GetUniqueAddress(crob.moduleId, iRpcMap, iStrMap, iSideMap, crob.rpcType);
+            else
+              fviRpcChUId[uCh] = 0;
+            uCh++;
+          }
+        }
+      }
+    }
+  }
 
   // -------------------------------------------------------------------------
   void ReadoutConfig::BuildChannelsUidMapBuc(uint32_t& uCh, const config::CROB& crob)
diff --git a/algo/detectors/tof/ReadoutConfig.h b/algo/detectors/tof/ReadoutConfig.h
index 0959c48b2646655d1ef0f2ce81c9d6d6261dc5fa..4b77c63789bbff4dd9959003d6b7a5043d0a52ec 100644
--- a/algo/detectors/tof/ReadoutConfig.h
+++ b/algo/detectors/tof/ReadoutConfig.h
@@ -56,6 +56,9 @@ namespace cbm::algo::tof
 
     /// Mapping to eLink to ASIC number within DPB. Mapping is the same for each DPB.
     int32_t ElinkIdxToGet4Idx(uint32_t elink, const config::ReadoutPars& pars);
+    /// Mapping to eLink to ASIC number within DPB for 2024 inner TOF FEBs. Mapping is the same for each DPB.
+    int32_t ElinkIdxToGet4IdxInner(uint32_t elink, const config::ReadoutPars& pars);
+
     int32_t Get4ChanToPadiChan(uint32_t channelInFee, const config::ReadoutPars& pars);
 
     std::vector<int32_t> fviRpcChUId = {};  // UID/address for each channel, build from type, side and module
@@ -66,6 +69,7 @@ namespace cbm::algo::tof
     void BuildChannelsUidMapCern(uint32_t& uCh, const config::CROB& crob);
     void BuildChannelsUidMapCera(uint32_t& uCh, const config::CROB& crob);
     void BuildChannelsUidMapStar2(uint32_t& uCh, const config::CROB& crob);
+    void BuildChannelsUidMapStar2Inner(uint32_t& uCh, const config::CROB& crob);
     void BuildChannelsUidMapBuc(uint32_t& uCh, const config::CROB& crob);
   };
 
diff --git a/algo/detectors/tof/config/ReadoutPars.h b/algo/detectors/tof/config/ReadoutPars.h
index bac8282523255ebdb7e41d50b3dc1b03f091c40f..f40b53c326a0f9f76273ba2eeb814a1affb85fae 100644
--- a/algo/detectors/tof/config/ReadoutPars.h
+++ b/algo/detectors/tof/config/ReadoutPars.h
@@ -20,6 +20,9 @@ namespace cbm::algo::tof::config
   struct ReadoutPars {
 
     static ReadoutPars MakeMCBM2022();
+    static ReadoutPars MakeMCBM2024();
+
+    bool mcbmTof2024 = false;
 
     i32 nFebsPerComponent;
     i32 nAsicsPerFeb;
@@ -36,6 +39,7 @@ namespace cbm::algo::tof::config
 
     // Mapping to eLink to ASIC number within CROB. Mapping is the same for each CROB. (size: nElinksPerCrob)
     std::vector<i32> elink2Asic;
+    std::vector<i32> elink2AsicInner;
 
     // Mapping in Readout chain PCBs
     // Map from GET4 channel to PADI channel
@@ -47,6 +51,9 @@ namespace cbm::algo::tof::config
     i32 NChansPerComponent() const { return nChannelsPerAsic * NElinksPerComponent(); }
     i32 NElinksPerCrob() const { return nAsicsPerFeb * NFebsPerCrob(); }
     i32 NElinksPerComponent() const { return NElinksPerCrob() * nCrobPerComponent; }
+
+    bool CheckBmonComp(uint32_t uCompId) const { return ((uCompId & 0xFFF0) == 0xABF0); }
+    bool CheckInnerComp(uint32_t uCompId) const { return ((uCompId & 0xFFF0) == 0xBBC0); }
   };
 
 }  // namespace cbm::algo::tof::config
diff --git a/algo/detectors/tof/config/ReadoutPars_mCBM2022.cxx b/algo/detectors/tof/config/ReadoutPars_mCBM2022.cxx
index 34713a4207d2a010be0c688d24a5ff6da70d9c65..18b1ef6aac7474103ba55022d5e7dc82e1f0f734 100644
--- a/algo/detectors/tof/config/ReadoutPars_mCBM2022.cxx
+++ b/algo/detectors/tof/config/ReadoutPars_mCBM2022.cxx
@@ -1,6 +1,7 @@
 /* Copyright (C) 2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
    SPDX-License-Identifier: GPL-3.0-only
    Authors: Felix Weiglhofer [committer], Dominik Smith */
+#include "Exceptions.h"
 #include "ReadoutPars.h"
 
 using namespace cbm::algo::tof::config;
@@ -46,6 +47,14 @@ ReadoutPars ReadoutPars::MakeMCBM2022()
     3,  2,  1,  0,  7,  6,  5,  4,  11, 10, 9,  8,  15, 14, 13, 12,
     19, 18, 17, 16, 23, 22, 21, 20, 27, 26, 25, 24, 31, 30, 29, 28};  //! Map from GET4 channel to PADI channel
 
+  if (pars.NElinksPerCrob() != static_cast<i32>(pars.elink2Asic.size())) {
+    throw FatalError("tof::ReadoutPars::MakeMCBM2022 => size of elink2Asic not matching, {} vs {}, stop there!",
+                     static_cast<uint32_t>(pars.elink2Asic.size()), static_cast<uint32_t>(pars.NElinksPerComponent()));
+  }
+  if (pars.NChansPerFeb() != static_cast<i32>(pars.asic2PadI.size())) {
+    throw FatalError("tof::ReadoutPars::MakeMCBM2022 => size of asic2PadI not matching, {} vs {}, stop there!",
+                     static_cast<uint32_t>(pars.elink2Asic.size()), static_cast<uint32_t>(pars.NChansPerFeb()));
+  }
 
   return pars;
 }
diff --git a/algo/detectors/tof/config/ReadoutPars_mCBM2024.cxx b/algo/detectors/tof/config/ReadoutPars_mCBM2024.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..d1fe95adaec1ecddcc99a543930e47034b873198
--- /dev/null
+++ b/algo/detectors/tof/config/ReadoutPars_mCBM2024.cxx
@@ -0,0 +1,69 @@
+/* Copyright (C) 2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Felix Weiglhofer [committer], Dominik Smith */
+#include "Exceptions.h"
+#include "ReadoutPars.h"
+
+using namespace cbm::algo::tof::config;
+
+ReadoutPars ReadoutPars::MakeMCBM2024()
+{
+  // This here refers to the mCBM 2022 and 2024 setups.
+  // Taken from CbmMcbm2018TofPar in combination with macro/beamtime/mcbm2022/mTofCriParNickel.par
+  // and mTofCriParNickel_withBmon.par (?)
+
+  ReadoutPars pars;
+
+  pars.mcbmTof2024 = true;
+
+  pars.nFebsPerComponent = 5;
+  pars.nAsicsPerFeb      = 8;
+  pars.nChannelsPerAsic  = 4;
+  pars.nCrobPerComponent = 1;
+
+  constexpr int NumCrob = 15;
+
+  // Module Identifier connected to Gbtx link, has to match geometry
+  const int32_t moduleId[NumCrob] = {0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 0, 0, 0, 1, 0};
+
+  // type of Rpcs connected to Gbtx link
+  const int32_t rpcType[NumCrob] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 9, 9, 6};
+
+  // side of Rpcs connected to Gbtx link, i.e. 0 or 1
+  const int32_t rpcSide[NumCrob] = {0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 2, 3};
+
+  // number of Rpcs connected to Gbtx link, i.e. 3 or 5
+  const int32_t numRpc[NumCrob] = {5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 2, 2, 5};
+
+  for (int i = 0; i < NumCrob; ++i) {
+    pars.crobs.push_back({moduleId[i], rpcType[i], rpcSide[i], numRpc[i]});
+  }
+
+  pars.eqIds = {0xabc0, 0xabc1, 0xabc2, 0xabc3, 0xabc4, 0xabc5, 0xabc6, 0xabc7,
+                0xabc8, 0xabc9, 0xabca, 0xabcb, 0xabcc, 0xabcd, 0xbbc0};
+
+  pars.elink2Asic      = {27, 2,  7,  3,  31, 26, 30, 1,  33, 37, 32, 13, 9,  14, 10, 15, 17, 21, 16, 35,
+                     34, 38, 25, 24, 0,  6,  20, 23, 18, 22, 28, 4,  29, 5,  19, 36, 39, 8,  12, 11};
+  pars.elink2AsicInner = {0, 16, 8,  17, 1, 18, 9,  19, 2, 20, 10, 21, 3,  22, 11, 23, 4,  24, 12, 25,
+                          5, 26, 13, 27, 6, 28, 14, 29, 7, 30, 15, 31, 32, 33, 34, 35, 36, 37, 38, 39};
+
+  // Mapping in Readout chain PCBs
+  pars.asic2PadI = {
+    3,  2,  1,  0,  7,  6,  5,  4,  11, 10, 9,  8,  15, 14, 13, 12,
+    19, 18, 17, 16, 23, 22, 21, 20, 27, 26, 25, 24, 31, 30, 29, 28};  //! Map from GET4 channel to PADI channel
+
+  if (pars.NElinksPerCrob() != static_cast<i32>(pars.elink2Asic.size())) {
+    throw FatalError("tof::ReadoutPars::MakeMCBM2024 => size of elink2Asic not matching, {} vs {}, stop there!",
+                     static_cast<uint32_t>(pars.elink2Asic.size()), static_cast<uint32_t>(pars.NElinksPerCrob()));
+  }
+  if (pars.NElinksPerCrob() != static_cast<i32>(pars.elink2AsicInner.size())) {
+    throw FatalError("tof::ReadoutPars::MakeMCBM2024 => size of elink2AsicInner not matching, {} vs {}, stop there!",
+                     static_cast<uint32_t>(pars.elink2Asic.size()), static_cast<uint32_t>(pars.NElinksPerCrob()));
+  }
+  if (pars.NChansPerFeb() != static_cast<i32>(pars.asic2PadI.size())) {
+    throw FatalError("tof::ReadoutPars::MakeMCBM2024 => size of asic2PadI not matching, {} vs {}, stop there!",
+                     static_cast<uint32_t>(pars.elink2Asic.size()), static_cast<uint32_t>(pars.NChansPerFeb()));
+  }
+
+  return pars;
+}
diff --git a/algo/global/Reco.cxx b/algo/global/Reco.cxx
index e308d7dc3ffe79bff64b9c4e218815c4ef0acc51..0da2d2f9b8c009ee29d3b6828224385edede13e2 100644
--- a/algo/global/Reco.cxx
+++ b/algo/global/Reco.cxx
@@ -125,7 +125,8 @@ void Reco::Init(const Options& opts)
   }
 
   if (Opts().Has(Subsystem::TOF) && Opts().Has(Step::Unpack)) {
-    tof::ReadoutConfig cfg{tof::config::ReadoutPars::MakeMCBM2022()};
+    tof::ReadoutConfig cfg{2724 <= Opts().RunId() ? tof::config::ReadoutPars::MakeMCBM2024()
+                                                  : tof::config::ReadoutPars::MakeMCBM2022()};
     fTofUnpack = std::make_unique<tof::Unpack>(cfg);
   }