From 7cb50288ef17578d9fd4f1a1615aa8e471454a28 Mon Sep 17 00:00:00 2001
From: Robert Schmidt <robert.schmidt@openairinterface.org>
Date: Fri, 24 Mar 2023 22:53:29 +0100
Subject: [PATCH] Refactor MIB handling

---
 openair1/SIMULATION/NR_PHY/dlsim.c            |  31 ++---
 openair1/SIMULATION/NR_PHY/ulsim.c            |  36 +++---
 openair2/GNB_APP/gnb_config.c                 |   8 +-
 .../LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c     |   2 +-
 openair2/RRC/LTE/rrc_defs.h                   |   1 -
 openair2/RRC/NR/L2_nr_interface.c             |  22 +---
 openair2/RRC/NR/MESSAGES/asn1_msg.c           | 103 ----------------
 openair2/RRC/NR/MESSAGES/asn1_msg.h           |   3 -
 openair2/RRC/NR/nr_rrc_config.c               | 112 ++++++++++++++++++
 openair2/RRC/NR/nr_rrc_config.h               |   5 +
 openair2/RRC/NR/nr_rrc_defs.h                 |   7 +-
 openair2/RRC/NR/rrc_gNB.c                     |  23 +---
 12 files changed, 161 insertions(+), 192 deletions(-)

diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c
index 5f9beb9ddc..207b7c4dae 100644
--- a/openair1/SIMULATION/NR_PHY/dlsim.c
+++ b/openair1/SIMULATION/NR_PHY/dlsim.c
@@ -58,7 +58,7 @@
 //#include "openair2/LAYER2/NR_MAC_UE/mac_proto.h"
 #include "LAYER2/NR_MAC_gNB/mac_proto.h"
 #include "NR_asn_constant.h"
-#include "RRC/NR/MESSAGES/asn1_msg.h"
+#include "RRC/NR/nr_rrc_config.h"
 #include "openair1/SIMULATION/RF/rf.h"
 #include "openair1/SIMULATION/TOOLS/sim.h"
 #include "openair1/SIMULATION/NR_PHY/nr_unitary_defs.h"
@@ -641,8 +641,6 @@ int main(int argc, char **argv)
     RC.nb_nr_mac_CC[i] = 1;
   mac_top_init_gNB(ngran_gNB);
   gNB_mac = RC.nrmac[0];
-  gNB_RRC_INST rrc;
-  memset((void*)&rrc,0,sizeof(rrc));
 
   gNB_mac->dl_bler.harq_round_max = num_rounds;
 
@@ -688,20 +686,16 @@ int main(int argc, char **argv)
   NR_ServingCellConfigCommon_t *scc = secondaryCellGroup->spCellConfig->reconfigurationWithSync->spCellConfigCommon;
   */
 
+  NR_ServingCellConfigCommon_t *scc = calloc(1,sizeof(*scc));;
+  prepare_scc(scc);
+  uint64_t ssb_bitmap = 1; // Enable only first SSB with index ssb_indx=0
+  fill_scc_sim(scc, &ssb_bitmap, N_RB_DL, N_RB_DL, mu, mu);
+  fix_scc(scc, ssb_bitmap);
 
-  rrc.carrier.servingcellconfigcommon = calloc(1,sizeof(*rrc.carrier.servingcellconfigcommon));
-
-  NR_ServingCellConfigCommon_t *scc = rrc.carrier.servingcellconfigcommon;
-  NR_ServingCellConfig_t *scd = calloc(1,sizeof(NR_ServingCellConfig_t));
-  NR_CellGroupConfig_t *secondaryCellGroup=calloc(1,sizeof(*secondaryCellGroup));
-  prepare_scc(rrc.carrier.servingcellconfigcommon);
-  uint64_t ssb_bitmap = 1;
-  fill_scc_sim(rrc.carrier.servingcellconfigcommon,&ssb_bitmap,N_RB_DL,N_RB_DL,mu,mu);
-  ssb_bitmap = 1;// Enable only first SSB with index ssb_indx=0
-  fix_scc(scc,ssb_bitmap);
+  NR_ServingCellConfig_t *scd = calloc(1,sizeof(*scd));
   prepare_scd(scd);
 
-  rrc_pdsch_AntennaPorts_t pdsch_AntennaPorts;
+  rrc_pdsch_AntennaPorts_t pdsch_AntennaPorts = {0};
   pdsch_AntennaPorts.N1 = n_tx>1 ? n_tx>>1 : 1;
   pdsch_AntennaPorts.N2 = 1;
   pdsch_AntennaPorts.XP = n_tx>1 ? 2 : 1;
@@ -723,10 +717,12 @@ int main(int argc, char **argv)
     .do_SRS = 0,
     .force_256qam_off = false
   };
+  NR_CellGroupConfig_t *secondaryCellGroup = calloc(1, sizeof(*secondaryCellGroup));
   fill_default_secondaryCellGroup(scc, scd, secondaryCellGroup, UE_Capability_nr, 0, 1, &conf, 0);
 
   /* RRC parameter validation for secondaryCellGroup */
   fix_scd(scd);
+
   /* -U option modify DMRS */
   if(modify_dmrs) {
     update_dmrs_config(secondaryCellGroup, dmrs_arg);
@@ -891,11 +887,8 @@ int main(int argc, char **argv)
   AssertFatal(input_fd==NULL,"Not ready for input signal file\n");
 
   //Configure UE
-  rrc.carrier.MIB = (uint8_t*) malloc(4);
-  rrc.carrier.sizeof_MIB = do_MIB_NR(&rrc,0);
-
-  nr_rrc_mac_config_req_ue(0,0,0,rrc.carrier.mib.message.choice.mib, NULL, NULL, secondaryCellGroup);
-
+  NR_BCCH_BCH_Message_t *mib = get_new_MIB_NR(scc);
+  nr_rrc_mac_config_req_ue(0, 0, 0, mib->message.choice.mib, NULL, NULL, secondaryCellGroup);
 
   nr_dcireq_t dcireq;
   nr_scheduled_response_t scheduled_response;
diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c
index d8ffdcc55e..2e4c82a7e5 100644
--- a/openair1/SIMULATION/NR_PHY/ulsim.c
+++ b/openair1/SIMULATION/NR_PHY/ulsim.c
@@ -53,7 +53,7 @@
 #include "openair1/SIMULATION/TOOLS/sim.h"
 #include "openair1/SIMULATION/RF/rf.h"
 #include "openair1/SIMULATION/NR_PHY/nr_unitary_defs.h"
-#include "openair2/RRC/NR/MESSAGES/asn1_msg.h"
+#include "openair2/RRC/NR/nr_rrc_config.h"
 #include "openair2/LAYER2/NR_MAC_UE/mac_proto.h"
 #include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h"
 #include "common/utils/threadPool/thread-pool.h"
@@ -621,23 +621,17 @@ int main(int argc, char **argv)
   for (i = 0; i < RC.nb_nr_macrlc_inst; i++)
     RC.nb_nr_mac_CC[i] = 1;
   mac_top_init_gNB(ngran_gNB);
-  //gNB_MAC_INST* gNB_mac = RC.nrmac[0];
-  gNB_RRC_INST rrc;
-  memset((void*)&rrc,0,sizeof(rrc));
 
-  rrc.carrier.servingcellconfigcommon = calloc(1,sizeof(*rrc.carrier.servingcellconfigcommon));
-
-  NR_ServingCellConfigCommon_t *scc = rrc.carrier.servingcellconfigcommon;
-  NR_ServingCellConfig_t *scd = calloc(1,sizeof(NR_ServingCellConfig_t));
-  NR_CellGroupConfig_t *secondaryCellGroup=calloc(1,sizeof(*secondaryCellGroup));
-  prepare_scc(rrc.carrier.servingcellconfigcommon);
+  NR_ServingCellConfigCommon_t *scc = calloc(1,sizeof(*scc));;
+  prepare_scc(scc);
   uint64_t ssb_bitmap;
-  fill_scc_sim(rrc.carrier.servingcellconfigcommon,&ssb_bitmap,N_RB_DL,N_RB_DL,mu,mu);
-
+  fill_scc_sim(scc, &ssb_bitmap, N_RB_DL, N_RB_DL, mu, mu);
   fix_scc(scc,ssb_bitmap);
 
+  NR_ServingCellConfig_t *scd = calloc(1,sizeof(NR_ServingCellConfig_t));
   prepare_scd(scd);
 
+  NR_CellGroupConfig_t *secondaryCellGroup=calloc(1,sizeof(*secondaryCellGroup));
   // TODO do a UECAP for phy-sim
   const gNB_RrcConfigurationReq conf = {
     .pdsch_AntennaPorts = { .N1 = 1, .N2 = 1, .XP = 1 },
@@ -649,17 +643,17 @@ int main(int argc, char **argv)
   };
   fill_default_secondaryCellGroup(scc, scd, secondaryCellGroup, NULL, 0, 1, &conf, 0);
 
-  // xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup);
-
   /* RRC parameter validation for secondaryCellGroup */
   fix_scd(scd);
 
+  NR_BCCH_BCH_Message_t *mib = get_new_MIB_NR(scc);
+
   AssertFatal((gNB->if_inst = NR_IF_Module_init(0))!=NULL,"Cannot register interface");
 
   gNB->if_inst->NR_PHY_config_req = nr_phy_config_request;
   // common configuration
   nr_mac_config_scc(RC.nrmac[0], conf.pdsch_AntennaPorts, n_tx, 0, 6, scc);
-  nr_mac_config_mib(RC.nrmac[0], &rrc.carrier.mib);
+  nr_mac_config_mib(RC.nrmac[0], mib);
   // UE dedicated configuration
   nr_mac_add_test_ue(RC.nrmac[0], secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity, secondaryCellGroup);
   frame_parms->nb_antennas_tx = 1;
@@ -731,12 +725,9 @@ int main(int argc, char **argv)
   }
 
   //Configure UE
-  NR_UE_RRC_INST_t rrcue;
-  memset(&rrcue,0,sizeof(NR_UE_RRC_INST_t));
-  rrc.carrier.MIB = (uint8_t*) malloc(4);
-  rrc.carrier.sizeof_MIB = do_MIB_NR(&rrc,0);
-  rrcue.mib = rrc.carrier.mib.message.choice.mib;
-  rrcue.scell_group_config=secondaryCellGroup;
+  NR_UE_RRC_INST_t rrcue = {0};
+  rrcue.mib = mib->message.choice.mib;
+  rrcue.scell_group_config = secondaryCellGroup;
   nr_l2_init_ue(&rrcue);
 
   NR_UE_MAC_INST_t* UE_mac = get_mac_inst(0);
@@ -1670,7 +1661,8 @@ int main(int argc, char **argv)
           mapping_type,
           length_dmrs,
           num_dmrs_cdm_grps_no_data);
-              
+
+  free_MIB_NR(mib);
   free(test_input_bit);
   free(estimated_output_bit);
   if (gNB->ldpc_offload_flag)
diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c
index 4ac0ba4d41..3705f62840 100644
--- a/openair2/GNB_APP/gnb_config.c
+++ b/openair2/GNB_APP/gnb_config.c
@@ -1896,8 +1896,12 @@ int RCconfig_NR_DU_F1(MessageDef *msg_p, uint32_t i) {
 
         f1Setup->measurement_timing_information[k]             = "0";
         f1Setup->ranac[k]                                      = 0;
-        f1Setup->mib[k]                                        = rrc->carrier.MIB;
-        f1Setup->mib_length[k]                                 = rrc->carrier.sizeof_MIB;
+        DevAssert(rrc->carrier.mib != NULL);
+        int buf_len = 3; // this is what we assume in monolithic
+        f1Setup->mib[k]                                        = calloc(buf_len, sizeof(*f1Setup->mib[k]));
+        DevAssert(f1Setup->mib[k] != NULL);
+        f1Setup->mib_length[k]                                 = encode_MIB_NR(rrc->carrier.mib, 0, f1Setup->mib[k], buf_len);
+        DevAssert(f1Setup->mib_length[k] == buf_len);
 
         NR_BCCH_DL_SCH_Message_t *bcch_message = NULL;
         asn_codec_ctx_t st={100*1000};
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c
index 37ceeddbee..c2b7b0964e 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c
@@ -94,7 +94,7 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP,
   gNB_MAC_INST *gNB = RC.nrmac[module_idP];
   NR_COMMON_channels_t *cc;
   nfapi_nr_dl_tti_request_body_t *dl_req;
-  NR_MIB_t *mib = RC.nrrrc[module_idP]->carrier.mib.message.choice.mib;
+  NR_MIB_t *mib = RC.nrrrc[module_idP]->carrier.mib->message.choice.mib;
   uint8_t num_tdd_period,num_ssb;
   int mib_sdu_length;
   int CC_id;
diff --git a/openair2/RRC/LTE/rrc_defs.h b/openair2/RRC/LTE/rrc_defs.h
index 6ce27da5ce..30f47b99ac 100644
--- a/openair2/RRC/LTE/rrc_defs.h
+++ b/openair2/RRC/LTE/rrc_defs.h
@@ -696,7 +696,6 @@ typedef struct {
   uint32_t                              N_RB_DL;
   uint32_t                              pbch_repetition;
   LTE_BCCH_BCH_Message_t                mib;
-  LTE_BCCH_BCH_Message_t                *mib_DU;
   LTE_BCCH_DL_SCH_Message_t             siblock1;
   LTE_BCCH_DL_SCH_Message_t             siblock1_BR;
   LTE_BCCH_DL_SCH_Message_t             *siblock1_DU;
diff --git a/openair2/RRC/NR/L2_nr_interface.c b/openair2/RRC/NR/L2_nr_interface.c
index 408c309310..20d5a6ec20 100644
--- a/openair2/RRC/NR/L2_nr_interface.c
+++ b/openair2/RRC/NR/L2_nr_interface.c
@@ -77,27 +77,13 @@ uint16_t mac_rrc_nr_data_req(const module_id_t Mod_idP,
   // MIBCH
   if ((Srb_id & RAB_OFFSET) == MIBCH) {
 
-    asn_enc_rval_t enc_rval;
-    uint8_t sfn_msb = (uint8_t)((frameP>>4)&0x3f);
+    int encode_size = 3;
     rrc_gNB_carrier_data_t *carrier = &RC.nrrrc[Mod_idP]->carrier;
-    NR_BCCH_BCH_Message_t *mib = &carrier->mib;
-
-    mib->message.choice.mib->systemFrameNumber.buf[0] = sfn_msb << 2;
-    enc_rval = uper_encode_to_buffer(&asn_DEF_NR_BCCH_BCH_Message,
-                                     NULL,
-                                     (void *) mib,
-                                     carrier->MIB,
-                                     24);
-    LOG_D(NR_RRC, "Encoded MIB for frame %d sfn_msb %d (%p), bits %lu\n", frameP, sfn_msb, carrier->MIB,
-          enc_rval.encoded);
-    buffer_pP[0] = carrier->MIB[0];
-    buffer_pP[1] = carrier->MIB[1];
-    buffer_pP[2] = carrier->MIB[2];
+    int encoded = encode_MIB_NR(carrier->mib, frameP, buffer_pP, encode_size);
+    DevAssert(encoded == encode_size);
     LOG_D(NR_RRC, "MIB PDU buffer_pP[0]=%x , buffer_pP[1]=%x, buffer_pP[2]=%x\n", buffer_pP[0], buffer_pP[1],
           buffer_pP[2]);
-    AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
-                 enc_rval.failed_type->name, enc_rval.encoded);
-    return 3;
+    return encode_size;
   }
 
   // TODO BCCH SIB1 SIBs
diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c
index 16a027fb50..92ecf37546 100644
--- a/openair2/RRC/NR/MESSAGES/asn1_msg.c
+++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c
@@ -194,109 +194,6 @@ int xer_nr_sprint (char *string, size_t string_size, asn_TYPE_descriptor_t *td,
 
 //------------------------------------------------------------------------------
 
-uint8_t do_MIB_NR(gNB_RRC_INST *rrc,uint32_t frame) { 
-
-  asn_enc_rval_t enc_rval;
-  rrc_gNB_carrier_data_t *carrier = &rrc->carrier;
-
-  NR_BCCH_BCH_Message_t *mib = &carrier->mib;
-  NR_ServingCellConfigCommon_t *scc = carrier->servingcellconfigcommon;
-
-  memset(mib,0,sizeof(NR_BCCH_BCH_Message_t));
-  mib->message.present = NR_BCCH_BCH_MessageType_PR_mib;
-  mib->message.choice.mib = CALLOC(1,sizeof(struct NR_MIB));
-  memset(mib->message.choice.mib,0,sizeof(struct NR_MIB));
-  //36.331 SFN BIT STRING (SIZE (8)  , 38.331 SFN BIT STRING (SIZE (6))
-  uint8_t sfn_msb = (uint8_t)((frame>>4)&0x3f);
-  mib->message.choice.mib->systemFrameNumber.buf = CALLOC(1,sizeof(uint8_t));
-  mib->message.choice.mib->systemFrameNumber.buf[0] = sfn_msb << 2;
-  mib->message.choice.mib->systemFrameNumber.size = 1;
-  mib->message.choice.mib->systemFrameNumber.bits_unused=2;
-  //38.331 spare BIT STRING (SIZE (1))
-  uint16_t *spare= CALLOC(1, sizeof(uint16_t));
-
-  if (spare == NULL) abort();
-
-  mib->message.choice.mib->spare.buf = (uint8_t *)spare;
-  mib->message.choice.mib->spare.size = 1;
-  mib->message.choice.mib->spare.bits_unused = 7;  // This makes a spare of 1 bits
-
-  AssertFatal(scc->ssbSubcarrierSpacing != NULL, "scc->ssbSubcarrierSpacing is null\n");
-  int band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0];
-  frequency_range_t frequency_range = band < 100 ? FR1 : FR2;
-  int ssb_subcarrier_offset = 31; // default value for NSA
-  if (get_softmodem_params()->sa) {
-    uint32_t absolute_diff = (*scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB - scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA);
-    int scs_scaling = scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA < 600000 ? 3 : 1;
-    ssb_subcarrier_offset = (absolute_diff/scs_scaling) % 24;
-    if(frequency_range == FR2)
-      ssb_subcarrier_offset >>= 1; // this assumes 120kHz SCS for SSB and subCarrierSpacingCommon (only option supported by OAI for now)
-  }
-  mib->message.choice.mib->ssb_SubcarrierOffset = ssb_subcarrier_offset & 15;
-
-  /*
-  * The SIB1 will be sent in this allocation (Type0-PDCCH) : 38.213, 13-4 Table and 38.213 13-11 to 13-14 tables
-  * the reverse allocation is in nr_ue_decode_mib()
-  */
-  const NR_PDCCH_ConfigCommon_t *pdcch_cc = scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup;
-  long cset0 = pdcch_cc->controlResourceSetZero ? *pdcch_cc->controlResourceSetZero : 0;
-  mib->message.choice.mib->pdcch_ConfigSIB1.controlResourceSetZero = cset0;
-  long ss0 = pdcch_cc->searchSpaceZero ? *pdcch_cc->searchSpaceZero : 0;
-  mib->message.choice.mib->pdcch_ConfigSIB1.searchSpaceZero = ss0;
-
-  switch (*scc->ssbSubcarrierSpacing) {
-  case NR_SubcarrierSpacing_kHz15:
-    mib->message.choice.mib->subCarrierSpacingCommon = NR_MIB__subCarrierSpacingCommon_scs15or60;
-    break;
-    
-  case NR_SubcarrierSpacing_kHz30:
-    mib->message.choice.mib->subCarrierSpacingCommon = NR_MIB__subCarrierSpacingCommon_scs30or120;
-    break;
-    
-  case NR_SubcarrierSpacing_kHz60:
-    mib->message.choice.mib->subCarrierSpacingCommon = NR_MIB__subCarrierSpacingCommon_scs15or60;
-    break;
-    
-  case NR_SubcarrierSpacing_kHz120:
-    mib->message.choice.mib->subCarrierSpacingCommon = NR_MIB__subCarrierSpacingCommon_scs30or120;
-    break;
-    
-  case NR_SubcarrierSpacing_kHz240:
-    AssertFatal(1==0,"Unknown subCarrierSpacingCommon %d\n",(int)*scc->ssbSubcarrierSpacing);
-    break;
-    
-  default:
-      AssertFatal(1==0,"Unknown subCarrierSpacingCommon %d\n",(int)*scc->ssbSubcarrierSpacing);
-  }
-
-  switch (scc->dmrs_TypeA_Position) {
-  case 	NR_ServingCellConfigCommon__dmrs_TypeA_Position_pos2:
-    mib->message.choice.mib->dmrs_TypeA_Position = NR_MIB__dmrs_TypeA_Position_pos2;
-    break;
-    
-  case 	NR_ServingCellConfigCommon__dmrs_TypeA_Position_pos3:
-    mib->message.choice.mib->dmrs_TypeA_Position = NR_MIB__dmrs_TypeA_Position_pos3;
-    break;
-    
-  default:
-    AssertFatal(1==0,"Unknown dmrs_TypeA_Position %d\n",(int)scc->dmrs_TypeA_Position);
-  }
-
-  //  assign_enum
-  mib->message.choice.mib->cellBarred = NR_MIB__cellBarred_notBarred;
-  //  assign_enum
-  mib->message.choice.mib->intraFreqReselection = NR_MIB__intraFreqReselection_notAllowed;
-  //encode MIB to data
-  enc_rval = uper_encode_to_buffer(&asn_DEF_NR_BCCH_BCH_Message,
-                                   NULL,
-                                   (void *)mib,
-                                   carrier->MIB,
-                                   24);
-  AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
-               enc_rval.failed_type->name, enc_rval.encoded);
-  return((enc_rval.encoded+7)/8);
-}
-
 uint16_t do_SIB1_NR(rrc_gNB_carrier_data_t *carrier,
                     gNB_RrcConfigurationReq *configuration) {
 
diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.h b/openair2/RRC/NR/MESSAGES/asn1_msg.h
index b5fa86bc6f..c51932a6fa 100644
--- a/openair2/RRC/NR/MESSAGES/asn1_msg.h
+++ b/openair2/RRC/NR/MESSAGES/asn1_msg.h
@@ -55,9 +55,6 @@
  */
 int xer_sprint_NR(char *string, size_t string_size, struct asn_TYPE_descriptor_s *td, void *sptr);
 
-uint8_t do_MIB_NR(gNB_RRC_INST *rrc,
-                  uint32_t frame);
-
 /**
 \brief Generate configuration for SIB1 (gNB).
 @param carrier pointer to Carrier information
diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c
index 2b989659b6..430399f561 100644
--- a/openair2/RRC/NR/nr_rrc_config.c
+++ b/openair2/RRC/NR/nr_rrc_config.c
@@ -1577,3 +1577,115 @@ void config_rsrp_meas_report(NR_CSI_MeasConfig_t *csi_MeasConfig,
   *csirep->groupBasedBeamReporting.choice.disabled->nrofReportedRS = NR_CSI_ReportConfig__groupBasedBeamReporting__disabled__nrofReportedRS_n1;
   asn1cSeqAdd(&csi_MeasConfig->csi_ReportConfigToAddModList->list, csirep);
 }
+
+NR_BCCH_BCH_Message_t *get_new_MIB_NR(const NR_ServingCellConfigCommon_t *scc)
+{
+  NR_BCCH_BCH_Message_t *mib = calloc(1, sizeof(*mib));
+  if (mib == NULL)
+    abort();
+  mib->message.present = NR_BCCH_BCH_MessageType_PR_mib;
+  mib->message.choice.mib = calloc(1, sizeof(struct NR_MIB));
+  if (mib->message.choice.mib == NULL)
+    abort();
+
+  // 36.331 SFN BIT STRING (SIZE (8)  , 38.331 SFN BIT STRING (SIZE (6))
+  uint8_t sfn_msb = 0; // encoding will update with the correct frame number
+  mib->message.choice.mib->systemFrameNumber.buf = CALLOC(1, sizeof(uint8_t));
+  mib->message.choice.mib->systemFrameNumber.buf[0] = sfn_msb << 2;
+  mib->message.choice.mib->systemFrameNumber.size = 1;
+  mib->message.choice.mib->systemFrameNumber.bits_unused = 2;
+
+  // 38.331 spare BIT STRING (SIZE (1))
+  uint16_t *spare = CALLOC(1, sizeof(uint16_t));
+  if (spare == NULL)
+    abort();
+  mib->message.choice.mib->spare.buf = (uint8_t *)spare;
+  mib->message.choice.mib->spare.size = 1;
+  mib->message.choice.mib->spare.bits_unused = 7; // This makes a spare of 1 bits
+
+  AssertFatal(scc->ssbSubcarrierSpacing != NULL, "scc->ssbSubcarrierSpacing is null\n");
+  int band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0];
+  frequency_range_t frequency_range = band < 100 ? FR1 : FR2;
+  int ssb_subcarrier_offset = 31; // default value for NSA
+  if (get_softmodem_params()->sa) {
+    uint32_t absolute_diff = (*scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB
+                              - scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA);
+    int scs_scaling = scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA < 600000 ? 3 : 1;
+    ssb_subcarrier_offset = (absolute_diff / scs_scaling) % 24;
+    if (frequency_range == FR2) {
+      // this assumes 120kHz SCS for SSB and subCarrierSpacingCommon (only
+      // option supported by OAI for now)
+      ssb_subcarrier_offset >>= 1;
+    }
+  }
+  mib->message.choice.mib->ssb_SubcarrierOffset = ssb_subcarrier_offset & 15;
+
+  /*
+   * The SIB1 will be sent in this allocation (Type0-PDCCH) : 38.213, 13-4 Table and 38.213 13-11 to 13-14 tables
+   * the reverse allocation is in nr_ue_decode_mib()
+   */
+  const NR_PDCCH_ConfigCommon_t *pdcch_cc = scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup;
+  long cset0 = pdcch_cc->controlResourceSetZero ? *pdcch_cc->controlResourceSetZero : 0;
+  mib->message.choice.mib->pdcch_ConfigSIB1.controlResourceSetZero = cset0;
+  long ss0 = pdcch_cc->searchSpaceZero ? *pdcch_cc->searchSpaceZero : 0;
+  mib->message.choice.mib->pdcch_ConfigSIB1.searchSpaceZero = ss0;
+
+  switch (*scc->ssbSubcarrierSpacing) {
+    case NR_SubcarrierSpacing_kHz15:
+      mib->message.choice.mib->subCarrierSpacingCommon = NR_MIB__subCarrierSpacingCommon_scs15or60;
+      break;
+
+    case NR_SubcarrierSpacing_kHz30:
+      mib->message.choice.mib->subCarrierSpacingCommon = NR_MIB__subCarrierSpacingCommon_scs30or120;
+      break;
+
+    case NR_SubcarrierSpacing_kHz60:
+      mib->message.choice.mib->subCarrierSpacingCommon = NR_MIB__subCarrierSpacingCommon_scs15or60;
+      break;
+
+    case NR_SubcarrierSpacing_kHz120:
+      mib->message.choice.mib->subCarrierSpacingCommon = NR_MIB__subCarrierSpacingCommon_scs30or120;
+      break;
+
+    case NR_SubcarrierSpacing_kHz240:
+      AssertFatal(1 == 0, "Unknown subCarrierSpacingCommon %d\n", (int)*scc->ssbSubcarrierSpacing);
+      break;
+
+    default:
+      AssertFatal(1 == 0, "Unknown subCarrierSpacingCommon %d\n", (int)*scc->ssbSubcarrierSpacing);
+  }
+
+  switch (scc->dmrs_TypeA_Position) {
+    case NR_ServingCellConfigCommon__dmrs_TypeA_Position_pos2:
+      mib->message.choice.mib->dmrs_TypeA_Position = NR_MIB__dmrs_TypeA_Position_pos2;
+      break;
+
+    case NR_ServingCellConfigCommon__dmrs_TypeA_Position_pos3:
+      mib->message.choice.mib->dmrs_TypeA_Position = NR_MIB__dmrs_TypeA_Position_pos3;
+      break;
+
+    default:
+      AssertFatal(1 == 0, "Unknown dmrs_TypeA_Position %d\n", (int)scc->dmrs_TypeA_Position);
+  }
+
+  mib->message.choice.mib->cellBarred = NR_MIB__cellBarred_notBarred;
+  mib->message.choice.mib->intraFreqReselection = NR_MIB__intraFreqReselection_notAllowed;
+  return mib;
+}
+
+void free_MIB_NR(NR_BCCH_BCH_Message_t *mib)
+{
+  ASN_STRUCT_FREE(asn_DEF_NR_BCCH_BCH_Message, mib);
+}
+
+int encode_MIB_NR(NR_BCCH_BCH_Message_t *mib, int frame, uint8_t *buf, int buf_size)
+{
+  DevAssert(mib != NULL && mib->message.choice.mib->systemFrameNumber.buf != NULL);
+  uint8_t sfn_msb = (uint8_t)((frame >> 4) & 0x3f);
+  *mib->message.choice.mib->systemFrameNumber.buf = sfn_msb << 2;
+
+  asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_BCCH_BCH_Message, NULL, mib, buf, buf_size);
+  AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded);
+  LOG_D(NR_RRC, "Encoded MIB for frame %d sfn_msb %d, bits %lu\n", frame, sfn_msb, enc_rval.encoded);
+  return (enc_rval.encoded + 7) / 8;
+}
diff --git a/openair2/RRC/NR/nr_rrc_config.h b/openair2/RRC/NR/nr_rrc_config.h
index 6d10823555..095ba716be 100644
--- a/openair2/RRC/NR/nr_rrc_config.h
+++ b/openair2/RRC/NR/nr_rrc_config.h
@@ -104,4 +104,9 @@ void config_uplinkBWP(NR_BWP_Uplink_t *ubwp,
                       NR_UE_NR_Capability_t *uecap);
 NR_MAC_CellGroupConfig_t *configure_mac_cellgroup(void);
 
+
+NR_BCCH_BCH_Message_t *get_new_MIB_NR(const NR_ServingCellConfigCommon_t *scc);
+void free_MIB_NR(NR_BCCH_BCH_Message_t *mib);
+int encode_MIB_NR(NR_BCCH_BCH_Message_t *mib, int frame, uint8_t *buf, int buf_size);
+
 #endif
diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h
index 335a368c6c..93acdeac7b 100644
--- a/openair2/RRC/NR/nr_rrc_defs.h
+++ b/openair2/RRC/NR/nr_rrc_defs.h
@@ -442,10 +442,6 @@ typedef struct rrc_gNB_ue_context_s {
 
 typedef struct {
 
-  // buffer that contains the encoded messages
-  uint8_t                                   *MIB;
-  uint8_t                                   sizeof_MIB;
-
   uint8_t                                   *SIB1;
   uint16_t                                  sizeof_SIB1;
 
@@ -454,8 +450,7 @@ typedef struct {
 
   int                                       physCellId;
 
-  NR_BCCH_BCH_Message_t                     mib;
-  NR_BCCH_BCH_Message_t                    *mib_DU;
+  NR_BCCH_BCH_Message_t                    *mib;
   NR_SIB1_t                                *siblock1_DU;
   NR_SIB1_t                                *sib1;
   NR_SIB2_t                                *sib2;
diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c
index 7e489e50e4..524befd70c 100644
--- a/openair2/RRC/NR/rrc_gNB.c
+++ b/openair2/RRC/NR/rrc_gNB.c
@@ -177,10 +177,8 @@ static void init_NR_SI(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *configuration
 {
 
   LOG_D(RRC,"%s()\n\n\n\n",__FUNCTION__);
-  if (NODE_IS_DU(rrc->node_type) || NODE_IS_MONOLITHIC(rrc->node_type)) {
-    rrc->carrier.MIB             = (uint8_t *) malloc16(4);
-    rrc->carrier.sizeof_MIB      = do_MIB_NR(rrc,0);
-  }
+  if (NODE_IS_DU(rrc->node_type) || NODE_IS_MONOLITHIC(rrc->node_type))
+    rrc->carrier.mib = get_new_MIB_NR(rrc->carrier.servingcellconfigcommon);
 
   if((get_softmodem_params()->sa) && ( (NODE_IS_DU(rrc->node_type) || NODE_IS_MONOLITHIC(rrc->node_type)))) {
     rrc->carrier.sizeof_SIB1 = do_SIB1_NR(&rrc->carrier,configuration);
@@ -204,7 +202,7 @@ static void init_NR_SI(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *configuration
                       rrc->configuration.sib1_tda,
                       rrc->configuration.minRXTXTIME,
                       rrc->carrier.servingcellconfigcommon);
-    nr_mac_config_mib(RC.nrmac[rrc->module_id], &rrc->carrier.mib);
+    nr_mac_config_mib(RC.nrmac[rrc->module_id], rrc->carrier.mib);
     if (get_softmodem_params()->sa)
       nr_mac_config_sib1(RC.nrmac[rrc->module_id], rrc->carrier.siblock1);
   }
@@ -407,7 +405,7 @@ static void rrc_gNB_generate_RRCSetup_for_RRCReestablishmentRequest(module_id_t
                     rrc_instance_p->configuration.sib1_tda,
                     rrc_instance_p->configuration.minRXTXTIME,
                     rrc_instance_p->carrier.servingcellconfigcommon);
-  nr_mac_config_mib(RC.nrmac[rrc_instance_p->module_id], &rrc_instance_p->carrier.mib);
+  nr_mac_config_mib(RC.nrmac[rrc_instance_p->module_id], rrc_instance_p->carrier.mib);
   nr_mac_config_sib1(RC.nrmac[rrc_instance_p->module_id], rrc_instance_p->carrier.siblock1);
 
   LOG_I(NR_RRC, " [RAPROC] rnti: %04x Logical Channel DL-CCCH, Generating RRCSetup (bytes %d)\n", rnti, size);
@@ -2413,26 +2411,17 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *f1_setup_req) {
 	//fixme: multi instance is not consistent here
 	F1AP_SETUP_RESP (msg_p).gNB_CU_name  = rrc->node_name;
         // check that CU rrc instance corresponds to mcc/mnc/cgi (normally cgi should be enough, but just in case)
-        rrc->carrier.MIB = malloc(f1_setup_req->mib_length[i]);
-        rrc->carrier.sizeof_MIB = f1_setup_req->mib_length[i];
-        LOG_W(NR_RRC, "instance %d mib length %d\n", i, f1_setup_req->mib_length[i]);
         LOG_W(NR_RRC, "instance %d sib1 length %d\n", i, f1_setup_req->sib1_length[i]);
-        memcpy((void *)rrc->carrier.MIB,f1_setup_req->mib[i],f1_setup_req->mib_length[i]);
+        AssertFatal(rrc->carrier.mib == NULL, "CU MIB is already initialized: double F1 setup request?\n");
         asn_dec_rval_t dec_rval = uper_decode_complete(NULL,
                                   &asn_DEF_NR_BCCH_BCH_Message,
-                                  (void **)&rrc->carrier.mib_DU,
+                                  (void **)&rrc->carrier.mib,
                                   f1_setup_req->mib[i],
                                   f1_setup_req->mib_length[i]);
         AssertFatal(dec_rval.code == RC_OK,
                     "[gNB_CU %"PRIu8"] Failed to decode NR_BCCH_BCH_MESSAGE (%zu bits)\n",
                     j,
                     dec_rval.consumed );
-        NR_BCCH_BCH_Message_t *mib = &rrc->carrier.mib;
-        NR_BCCH_BCH_Message_t *mib_DU = rrc->carrier.mib_DU;
-        mib->message.present = NR_BCCH_BCH_MessageType_PR_mib;
-        mib->message.choice.mib = CALLOC(1,sizeof(struct NR_MIB));
-        memset(mib->message.choice.mib,0,sizeof(struct NR_MIB));
-        memcpy(mib->message.choice.mib, mib_DU->message.choice.mib, sizeof(struct NR_MIB));
 
         dec_rval = uper_decode_complete(NULL,
                                         &asn_DEF_NR_SIB1, //&asn_DEF_NR_BCCH_DL_SCH_Message,
-- 
2.26.2