diff --git a/cbxp/control_block_explorer.cpp b/cbxp/control_block_explorer.cpp index 21b352f..548bd42 100644 --- a/cbxp/control_block_explorer.cpp +++ b/cbxp/control_block_explorer.cpp @@ -13,6 +13,7 @@ #include "control_blocks/control_block.hpp" #include "control_blocks/cvt.hpp" #include "control_blocks/ecvt.hpp" +#include "control_blocks/ldax.hpp" #include "control_blocks/oucb.hpp" #include "control_blocks/psa.hpp" #include "logger.hpp" @@ -112,6 +113,10 @@ void ControlBlockExplorer::processControlBlock( } else if (control_block_name == "oucb") { control_block_json = OUCB(cbxp_options_).get(p_control_block_, control_block_data_length_); + } else if (control_block_name == "ldax") { + control_block_json = + LDAX(cbxp_options_).get(p_control_block_, control_block_data_length_); + } else { throw ControlBlockError(); } diff --git a/cbxp/control_blocks/assb.cpp b/cbxp/control_blocks/assb.cpp index 179358b..c261b73 100644 --- a/cbxp/control_blocks/assb.cpp +++ b/cbxp/control_blocks/assb.cpp @@ -10,6 +10,7 @@ #include "ascb.hpp" #include "asvt.hpp" +#include "ldax.hpp" #include "logger.hpp" namespace CBXP { @@ -63,6 +64,19 @@ nlohmann::json ASSB::get(const void* p_control_block, Logger::getInstance().hexDump(reinterpret_cast(p_assb), sizeof(struct assb)); + assb_json["assbldax"] = formatter_.getHex(&(p_assb->assbldax)); + + for (const auto& [include, cbxp_options] : options_map_) { + if (include == "ldax") { + assb_json["assbldax"] = + CBXP::LDAX(cbxp_options) + .get(*reinterpret_cast(p_assb->assbldax)); + if (assb_json["assbldax"].is_null()) { + return {}; + } + } + } + assb_json["assb_cms_lockinst_addr"] = formatter_.getHex(&(p_assb->assb_cms_lockinst_addr)); assb_json["assb_enqdeq_cms_lockinst_addr"] = @@ -78,7 +92,6 @@ nlohmann::json ASSB::get(const void* p_control_block, assb_json["assboasb"] = formatter_.getHex(&(p_assb->assboasb)); assb_json["assbtasb"] = formatter_.getHex(&(p_assb->assbtasb)); assb_json["assbvab"] = formatter_.getHex(&(p_assb->assbvab)); - assb_json["assbldax"] = formatter_.getHex(&(p_assb->assbldax)); assb_json["assbisqn"] = p_assb->assbisqn; assb_json["assbjbni"] = formatter_.getString(p_assb->assbjbni, 8); assb_json["assbjbns"] = formatter_.getString(p_assb->assbjbns, 8); diff --git a/cbxp/control_blocks/assb.hpp b/cbxp/control_blocks/assb.hpp index 5f6b0d2..9f0c720 100644 --- a/cbxp/control_blocks/assb.hpp +++ b/cbxp/control_blocks/assb.hpp @@ -12,7 +12,7 @@ class ASSB : public ControlBlock { nlohmann::json get(const void* p_control_block = nullptr, const size_t buffer_length = 0) override; explicit ASSB(const cbxp_options_t& cbxp_options) - : ControlBlock("assb", {}, cbxp_options, sizeof(struct assb)) {} + : ControlBlock("assb", {"ldax"}, cbxp_options, sizeof(struct assb)) {} }; } // namespace CBXP diff --git a/cbxp/control_blocks/control_block.cpp b/cbxp/control_blocks/control_block.cpp index b3ffe1b..cdc771f 100644 --- a/cbxp/control_blocks/control_block.cpp +++ b/cbxp/control_blocks/control_block.cpp @@ -195,7 +195,7 @@ bool ControlBlock::compare(const nlohmann::json& json_value, uint64_t value_uint; if (json_value.is_number()) { - value_uint = json_value.get(); + value_uint = json_value.get(); } else { value_str = json_value.get(); value_is_string = true; diff --git a/cbxp/control_blocks/ldax.cpp b/cbxp/control_blocks/ldax.cpp new file mode 100644 index 0000000..45f30a9 --- /dev/null +++ b/cbxp/control_blocks/ldax.cpp @@ -0,0 +1,130 @@ +#include "ldax.hpp" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "asvt.hpp" +#include "logger.hpp" + +namespace CBXP { + +nlohmann::json LDAX::get(const void* p_control_block, + const size_t buffer_length) { + LDAX::checkDataLength(buffer_length); + const struct ldax* p_ldax; + nlohmann::json ldax_json = {}; + if (p_control_block == nullptr) { + // PSA starts at address 0 + const struct psa* __ptr32 p_psa = 0; + + const struct cvtmap* __ptr32 p_cvtmap = + // cppcheck-suppress nullPointer + static_cast(p_psa->flccvt); + + const asvt_t* __ptr32 p_asvt = + static_cast(p_cvtmap->cvtasvt); + + ldax_json["ldaxs"] = std::vector(); + std::vector& ldaxs = + ldax_json["ldaxs"].get_ref&>(); + + ldaxs.reserve(p_asvt->asvtmaxu); + + const uint32_t* __ptr32 p_ascb_addr = + reinterpret_cast(&(p_asvt->asvtenty)); + + for (int i = 0; i < p_asvt->asvtmaxu; i++) { + if (0x80000000 & *p_ascb_addr) { + Logger::getInstance().debug(formatter_.getHex(p_ascb_addr) + + " is not a valid ASCB address"); + p_ascb_addr++; + continue; + } + + // Cast ASCB address into ASCB pointer + const struct ascb* __ptr32 p_ascb = + reinterpret_cast(*p_ascb_addr); + + // Get ASSB from ASCB + const struct assb* __ptr32 p_assb = + reinterpret_cast(p_ascb->ascbassb); + + nlohmann::json next_ldax = + LDAX::get(*reinterpret_cast(p_assb->assbldax)); + if (!next_ldax.is_null()) { + ldaxs.push_back(next_ldax); + } + + p_ascb_addr++; + } + + return ldaxs; + } else { + p_ldax = static_cast(p_control_block); + } + + Logger::getInstance().debug("ldax hex dump:"); + Logger::getInstance().hexDump(reinterpret_cast(p_ldax), + sizeof(struct ldax)); + + ldax_json["ldax_id"] = formatter_.getString(p_ldax->ldax_id, 4); + ldax_json["ldax_version"] = + formatter_.getBitmap(p_ldax->ldax_version); + ldax_json["ldax_ldaascb"] = + formatter_.getHex(&(p_ldax->ldax_ldaascb)); + ldax_json["ldax_ldastrta"] = + formatter_.getHex(&(p_ldax->ldax_ldastrta)); + ldax_json["ldax_ldasiza"] = p_ldax->ldax_ldasiza; + ldax_json["ldax_ldaestra"] = + formatter_.getHex(&(p_ldax->ldax_ldaestra)); + ldax_json["ldax_ldaesiza"] = p_ldax->ldax_ldaesiza; + ldax_json["ldax_ldacrgtp"] = + formatter_.getHex(&(p_ldax->ldax_ldacrgtp)); + ldax_json["ldax_ldaergtp"] = + formatter_.getHex(&(p_ldax->ldax_ldaergtp)); + ldax_json["ldax_ldalimit"] = + formatter_.getHex(&(p_ldax->ldax_ldalimit)); + ldax_json["ldax_ldavvrg"] = + formatter_.getHex(&(p_ldax->ldax_ldavvrg)); + ldax_json["ldax_ldaelim"] = + formatter_.getHex(&(p_ldax->ldax_ldaelim)); + ldax_json["ldax_ldaevvrg"] = + formatter_.getHex(&(p_ldax->ldax_ldaevvrg)); + ldax_json["ldax_ldaloal"] = + formatter_.getBitmap(p_ldax->ldax_ldaloal); + ldax_json["ldax_ldahial"] = + formatter_.getBitmap(p_ldax->ldax_ldahial); + ldax_json["ldax_ldaeloal"] = + formatter_.getBitmap(p_ldax->ldax_ldaeloal); + ldax_json["ldax_ldaehial"] = + formatter_.getBitmap(p_ldax->ldax_ldaehial); + ldax_json["ldax_tcthwm"] = p_ldax->ldax_tcthwm; + ldax_json["ldax_tctlwm"] = p_ldax->ldax_tctlwm; + ldax_json["ldax_tctehwm"] = p_ldax->ldax_tctehwm; + ldax_json["ldax_tctelwm"] = p_ldax->ldax_tctelwm; + ldax_json["ldax_curhighbot"] = + formatter_.getHex(&(p_ldax->ldax_curhighbot)); + ldax_json["ldax_curehighbot"] = + formatter_.getHex(&(p_ldax->ldax_curehighbot)); + ldax_json["ldax_ldasmad"] = + formatter_.getHex(&(p_ldax->ldax_ldasmad)); + ldax_json["ldax_ldasmsz"] = + formatter_.getHex(&(p_ldax->ldax_ldasmsz)); + ldax_json["ldax_obtainshomespace"] = p_ldax->ldax_obtainshomespace; + + if (LDAX::matchFilter(ldax_json)) { + return ldax_json; + } else { + return {}; + } +} + +} // namespace CBXP diff --git a/cbxp/control_blocks/ldax.hpp b/cbxp/control_blocks/ldax.hpp new file mode 100644 index 0000000..0878206 --- /dev/null +++ b/cbxp/control_blocks/ldax.hpp @@ -0,0 +1,20 @@ +#ifndef __LDAX_H_ +#define __LDAX_H_ + +#include + +#include "control_block.hpp" + +namespace CBXP { + +class LDAX : public ControlBlock { + public: + nlohmann::json get(const void* p_control_block = nullptr, + const size_t buffer_length = 0) override; + explicit LDAX(const cbxp_options_t& cbxp_options) + : ControlBlock("ldax", {}, cbxp_options, sizeof(struct ldax)) {} +}; + +} // namespace CBXP + +#endif diff --git a/tests/test.py b/tests/test.py index 84ed572..c8cf970 100644 --- a/tests/test.py +++ b/tests/test.py @@ -57,6 +57,12 @@ def test_cbxp_extract_oucb(self): for entry in cbdata: self.assertIs(type(entry), dict) + def test_cbxp_extract_ldax(self): + cbdata = cbxp.extract("ldax") + self.assertIs(type(cbdata), list) + for entry in cbdata: + self.assertIs(type(entry), dict) + # ============================================================================ # Extract -- Debug Mode # ============================================================================ @@ -106,6 +112,41 @@ def test_cbxp_extract_ascb_and_include_oucb(self): self.assertIs(type(entry), dict) self.assertIs(type(entry["ascboucb"]), dict) + def test_cbxp_extract_asvt_and_include_ascb_assb_ldax(self): + cbdata = cbxp.extract("asvt", includes=["ascb.assb.ldax"]) + self.assertIs(type(cbdata), dict) + self.assertIs(type(cbdata["asvtenty"]), list) + for entry in cbdata["asvtenty"]: + self.assertIs(type(entry), dict) + self.assertIs(type(entry["ascbassb"]), dict) + self.assertIs(type(entry["ascbassb"]["assbldax"]), dict) + + def test_cbxp_extract_psa_and_include_cvt_asvt_ascb_assb_ldax(self): + cbdata = cbxp.extract("psa", includes=["cvt.asvt.ascb.assb.ldax"]) + self.assertIs(type(cbdata), dict) + self.assertIs(type(cbdata["flccvt"]), dict) + self.assertIs(type(cbdata["flccvt"]["cvtasvt"]), dict) + self.assertIs(type(cbdata["flccvt"]["cvtasvt"]["asvtenty"]), list) + for entry in cbdata["flccvt"]["cvtasvt"]["asvtenty"]: + self.assertIs(type(entry), dict) + self.assertIs(type(entry["ascbassb"]), dict) + self.assertIs(type(entry["ascbassb"]["assbldax"]), dict) + + def test_cbxp_extract_assb_and_include_ldax(self): + cbdata = cbxp.extract("assb", includes=["ldax"]) + self.assertIs(type(cbdata), list) + for entry in cbdata: + self.assertIs(type(entry), dict) + self.assertIs(type(entry["assbldax"]), dict) + + def test_cbxp_extract_ascb_and_include_assb_ldax(self): + cbdata = cbxp.extract("ascb", includes=["assb.ldax"]) + self.assertIs(type(cbdata), list) + for entry in cbdata: + self.assertIs(type(entry), dict) + self.assertIs(type(entry["ascbassb"]), dict) + self.assertIs(type(entry["ascbassb"]["assbldax"]), dict) + def test_cbxp_extract_psa_and_include_cvt_ecvt(self): cbdata = cbxp.extract("psa", includes=["cvt.ecvt"]) self.assertIs(type(cbdata), dict) @@ -186,6 +227,7 @@ def test_cbxp_extract_psa_and_include_cvt_recursive_wildcard(self): for entry in cbdata["flccvt"]["cvtasvt"]["asvtenty"]: self.assertIs(type(entry), dict) self.assertIs(type(entry["ascbassb"]), dict) + self.assertIs(type(entry["ascbassb"]["assbldax"]), dict) self.assertIs(type(entry["ascboucb"]), dict) def test_cbxp_extract_psa_and_include_cvt_wildcard(self): @@ -220,6 +262,23 @@ def test_cbxp_extract_cvt_and_include_wildcard_and_asvt_recursive_wildcard( self.assertIs(type(entry["ascbassb"]), dict) self.assertIs(type(entry["ascboucb"]), dict) + def test_cbxp_extract_ascb_and_include_assb_recursive_wildcard(self): + cbdata = cbxp.extract("ascb", includes=["assb.**"]) + self.assertIs(type(cbdata), list) + for entry in cbdata: + self.assertIs(type(entry), dict) + self.assertIs(type(entry["ascbassb"]), dict) + self.assertIs(type(entry["ascbassb"]["assbldax"]), dict) + + def test_cbxp_extract_ascb_and_include_oucb_and_assb_recursive_wildcard(self): + cbdata = cbxp.extract("ascb", includes=["oucb", "assb.**"]) + self.assertIs(type(cbdata), list) + for entry in cbdata: + self.assertIs(type(entry), dict) + self.assertIs(type(entry["ascbassb"]), dict) + self.assertIs(type(entry["ascbassb"]["assbldax"]), dict) + self.assertIs(type(entry["ascboucb"]), dict) + # ============================================================================ # Extract -- Filters # ============================================================================ @@ -489,6 +548,55 @@ def test_cbxp_extract_filter_on_ascb_oucb_oucbtrxn_with_explicit_include_oucb(se self.assertIs(type(entry["ascboucb"]), dict) self.assertEqual(entry["ascboucb"]["oucbtrxn"], "OMVS") + def test_cbxp_extract_filter_on_ldax_tcthwm_equal(self): + cbdata = cbxp.extract( + "ldax", + filters=[ + CBXPFilter( + "ldax_tcthwm", + CBXPFilterOperation.EQUAL, + 0, + ), + ], + ) + self.assertIs(type(cbdata), list) + for entry in cbdata: + self.assertIs(type(entry), dict) + self.assertEqual(entry["ldax_tcthwm"], 0) + + def test_cbxp_extract_filter_on_psa_cvt_asvt_ascb_assb_ldax_tcthwm_with_include( + self, + ): + cbdata = cbxp.extract( + "psa", + filters=[ + CBXPFilter( + "cvt.asvt.ascb.assb.ldax.ldax_tcthwm", + CBXPFilterOperation.EQUAL, + 0, + ), + ], + includes=["cvt.asvt.ascb.assb.ldax"], + ) + self.assertIs(type(cbdata), dict) + self.assertIn("flccvt", cbdata) + self.assertIs(type(cbdata["flccvt"]), dict) + self.assertIn("cvtasvt", cbdata["flccvt"]) + self.assertIs(type(cbdata["flccvt"]["cvtasvt"]), dict) + self.assertIn("asvtenty", cbdata["flccvt"]["cvtasvt"]) + self.assertIs(type(cbdata["flccvt"]["cvtasvt"]["asvtenty"]), list) + # Verify at least one entry matches the filter + self.assertGreater(len(cbdata["flccvt"]["cvtasvt"]["asvtenty"]), 0) + for entry in cbdata["flccvt"]["cvtasvt"]["asvtenty"]: + self.assertIs(type(entry), dict) + self.assertIn("ascbassb", entry) + self.assertIs(type(entry["ascbassb"]), dict) + self.assertIn("assbldax", entry["ascbassb"]) + self.assertIs(type(entry["ascbassb"]["assbldax"]), dict) + self.assertEqual( + entry["ascbassb"]["assbldax"]["ldax_tcthwm"], 0, + ) + def test_cbxp_extract_null_filter_string( self, ): @@ -657,6 +765,20 @@ def test_cbxp_extract_raises_cbxp_error_if_filter_has_comma( ) self.assertEqual("Filters cannot contain commas", str(e.exception)) + def test_cbxp_extract_raises_cbxp_error_if_ldax_included_with_psa(self): + with self.assertRaises(CBXPError) as e: + cbxp.extract("psa", includes=["ldax"]) + self.assertEqual("A bad include pattern was provided", str(e.exception)) + + def test_cbxp_extract_raises_cbxp_error_if_ldax_included_with_cvt(self): + with self.assertRaises(CBXPError) as e: + cbxp.extract("cvt", includes=["ldax"]) + self.assertEqual("A bad include pattern was provided", str(e.exception)) + + def test_cbxp_extract_raises_cbxp_error_if_ldax_included_with_ascb(self): + with self.assertRaises(CBXPError) as e: + cbxp.extract("ascb", includes=["ldax"]) + self.assertEqual("A bad include pattern was provided", str(e.exception)) # ============================================================================ # Format -- Basic Usage # ============================================================================ diff --git a/tests/test.sh b/tests/test.sh index 43d8593..8ff24c3 100755 --- a/tests/test.sh +++ b/tests/test.sh @@ -54,6 +54,7 @@ run_with_expected_exit_code 0 ./dist/cbxp extract asvt run_with_expected_exit_code 0 ./dist/cbxp extract ascb run_with_expected_exit_code 0 ./dist/cbxp extract assb run_with_expected_exit_code 0 ./dist/cbxp extract oucb +run_with_expected_exit_code 0 ./dist/cbxp extract ldax # Extract - Debug Mode run_with_expected_exit_code 0 ./dist/cbxp extract -d psa run_with_expected_exit_code 0 ./dist/cbxp extract --debug psa @@ -75,6 +76,13 @@ run_with_expected_exit_code 0 ./dist/cbxp extract -i assb ascb run_with_expected_exit_code 0 ./dist/cbxp extract -i oucb ascb run_with_expected_exit_code 0 ./dist/cbxp extract -i cvt.ecvt -i cvt.asvt.ascb.assb psa run_with_expected_exit_code 0 ./dist/cbxp extract -i cvt.ecvt -i cvt.asvt.ascb.oucb psa +run_with_expected_exit_code 0 ./dist/cbxp extract -i "*" assb +run_with_expected_exit_code 0 ./dist/cbxp extract -i "**" assb +run_with_expected_exit_code 0 ./dist/cbxp extract -i "assb.**" ascb +run_with_expected_exit_code 0 ./dist/cbxp extract -i ldax assb +run_with_expected_exit_code 0 ./dist/cbxp extract -i assb.ldax ascb +run_with_expected_exit_code 0 ./dist/cbxp extract -i ascb.assb.ldax asvt +run_with_expected_exit_code 0 ./dist/cbxp extract -i cvt.asvt.ascb.assb.ldax psa # Extract - Filters run_with_expected_exit_code 0 ./dist/cbxp extract -f psapsa=PSA psa run_with_expected_exit_code 0 ./dist/cbxp extract -f "cvt.asvt.ascb.assb.assbjbns=*MASTER*" -i "**" psa @@ -99,6 +107,9 @@ run_with_expected_null_response ./dist/cbxp extract -f "ascb.assb.assbjbns=*MAST run_with_expected_exit_code 0 ./dist/cbxp extract -f assbjbns="*MASTER*" -f assbjbni= assb run_with_expected_exit_code 0 ./dist/cbxp extract -f assbjbns="*MASTER*" -f assbjbni="" assb run_with_expected_exit_code 0 ./dist/cbxp extract -f assbjbns="*MASTER*" -f assbjbni='' assb +run_with_expected_exit_code 0 ./dist/cbxp extract -f "cvt.asvt.ascb.assb.ldax.ldax_tcthwm=0" -i cvt.asvt.ascb.assb.ldax psa +run_with_expected_exit_code 0 ./dist/cbxp extract -f "ldax_tcthwm=0" ldax +run_with_expected_null_response ./dist/cbxp extract -f "cvt.asvt.ascb.assb.ldax.ldax_id=INVALID" -i cvt.asvt.ascb.assb.ldax psa # Extract - Errors: Bad Usage run_with_expected_exit_code 255 ./dist/cbxp extract run_with_expected_exit_code 255 ./dist/cbxp extract --junk @@ -121,6 +132,9 @@ run_with_expected_exit_code 255 ./dist/cbxp extract -i ecvt ascb run_with_expected_exit_code 255 ./dist/cbxp extract -i cvt.ecvt -i cvt.ascb psa run_with_expected_exit_code 255 ./dist/cbxp extract -i cvt.asvt.ascb -i ecvt psa run_with_expected_exit_code 255 ./dist/cbxp extract -i cvt cvt +run_with_expected_exit_code 255 ./dist/cbxp extract -i ldax psa +run_with_expected_exit_code 255 ./dist/cbxp extract -i ldax cvt +run_with_expected_exit_code 255 ./dist/cbxp extract -i ldax ascb # Extract - Errors: Bad Filters run_with_expected_exit_code 255 ./dist/cbxp extract -f "cvt.asvt.ascb.assb.assbjbns=*master*" psa run_with_expected_exit_code 255 ./dist/cbxp extract -f "cvt.asvt.ascb.assb.assbjbns<*master*" -i "**" psa