Skip to content

Commit 5ca2a32

Browse files
committed
feat(fl): add enable command and unit tests
- Add cmd_enable() function to fl.c for enabling/disabling patches - Add --enable option (0 or 1) with --comp and --all support - Add 7 unit tests for enable command in test_fl.c
1 parent 5a1a0f9 commit 5ca2a32

2 files changed

Lines changed: 191 additions & 0 deletions

File tree

App/func_loader/fl.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,32 @@ static void cmd_unpatch(fl_context_t* ctx, uint32_t comp, bool all) {
633633
}
634634
}
635635

636+
static void cmd_enable(fl_context_t* ctx, uint32_t comp, bool enable, bool all) {
637+
(void)ctx;
638+
uint32_t num_comps = fpb_get_state()->num_code_comp;
639+
uint32_t start = all ? 0 : comp;
640+
uint32_t end = all ? num_comps : comp + 1;
641+
642+
if (!all && (comp >= num_comps || comp >= FL_MAX_SLOTS)) {
643+
fl_response(false, "Invalid comp %lu", (unsigned long)comp);
644+
return;
645+
}
646+
647+
uint32_t changed = 0;
648+
for (uint32_t i = start; i < end && i < FL_MAX_SLOTS; i++) {
649+
fpb_result_t ret = fpb_enable_patch(i, enable);
650+
if (ret == FPB_OK) {
651+
changed++;
652+
}
653+
}
654+
655+
if (all) {
656+
fl_response(true, "%s %u patches", enable ? "Enabled" : "Disabled", (unsigned)changed);
657+
} else {
658+
fl_response(true, "%s patch %lu", enable ? "Enabled" : "Disabled", (unsigned long)comp);
659+
}
660+
}
661+
636662
__attribute__((noinline)) void fl_hello(void) {
637663
fl_println("Hello from original fl_hello!");
638664
fl_println("Inject a new version to change this message.");
@@ -958,6 +984,7 @@ int fl_exec_cmd(fl_context_t* ctx, int argc, const char** argv) {
958984
int size = 0;
959985
int comp = 0;
960986
int all = 0;
987+
int enable = -1; /* -1 = not specified, 0 = disable, 1 = enable */
961988
int force = 0;
962989
const char* path = NULL;
963990
const char* newpath = NULL;
@@ -975,6 +1002,7 @@ int fl_exec_cmd(fl_context_t* ctx, int argc, const char** argv) {
9751002
OPT_POINTER(0, "orig", &orig, "Original addr", NULL, 0, 0),
9761003
OPT_POINTER(0, "target", &target, "Target addr", NULL, 0, 0),
9771004
OPT_BOOLEAN(0, "all", &all, "Clear all", NULL, 0, 0),
1005+
OPT_INTEGER(0, "enable", &enable, "Enable(1) or disable(0) patch", NULL, 0, 0),
9781006
OPT_BOOLEAN(0, "force", &force, "Skip address range check", NULL, 0, 0),
9791007
OPT_STRING(0, "path", &path, "File path", NULL, 0, 0),
9801008
OPT_STRING(0, "newpath", &newpath, "New file path", NULL, 0, 0),
@@ -1043,6 +1071,12 @@ int fl_exec_cmd(fl_context_t* ctx, int argc, const char** argv) {
10431071
cmd_dpatch(ctx, comp, orig, target, crc);
10441072
} else if (strcmp(cmd, "unpatch") == 0) {
10451073
cmd_unpatch(ctx, comp, all);
1074+
} else if (strcmp(cmd, "enable") == 0) {
1075+
if (enable < 0) {
1076+
fl_response(false, "Missing --enable (0 or 1)");
1077+
return -1;
1078+
}
1079+
cmd_enable(ctx, comp, enable != 0, all);
10461080
#if FL_USE_FILE
10471081
/* File transfer commands */
10481082
} else if (strcmp(cmd, "fopen") == 0) {

App/tests/test_fl.c

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1241,6 +1241,153 @@ void test_loader_cmd_run_no_alloc(void) {
12411241
TEST_ASSERT(output != NULL);
12421242
}
12431243

1244+
/* ============================================================================
1245+
* fl_exec_cmd Tests - Enable Command
1246+
* ============================================================================ */
1247+
1248+
void test_loader_cmd_enable_missing_arg(void) {
1249+
setup_loader();
1250+
fl_init(&test_ctx);
1251+
1252+
/* enable command without --enable argument should fail */
1253+
const char* argv[] = {"fl", "--cmd", "enable", "--comp", "0"};
1254+
int result = fl_exec_cmd(&test_ctx, 5, argv);
1255+
1256+
TEST_ASSERT(result != 0);
1257+
TEST_ASSERT(mock_output_contains("Missing --enable"));
1258+
}
1259+
1260+
void test_loader_cmd_enable_single_disable(void) {
1261+
setup_loader();
1262+
fl_init(&test_ctx);
1263+
1264+
/* First set up a patch */
1265+
const char* alloc_argv[] = {"fl", "--cmd", "alloc", "--size", "64"};
1266+
fl_exec_cmd(&test_ctx, 5, alloc_argv);
1267+
1268+
const char* patch_argv[]
1269+
= {"fl", "--cmd", "patch", "--comp", "0", "--orig", "0x08001000", "--target", "0x20000100"};
1270+
fl_exec_cmd(&test_ctx, 9, patch_argv);
1271+
1272+
mock_output_reset();
1273+
1274+
/* Disable the patch */
1275+
const char* argv[] = {"fl", "--cmd", "enable", "--comp", "0", "--enable", "0"};
1276+
int result = fl_exec_cmd(&test_ctx, 7, argv);
1277+
1278+
TEST_ASSERT_EQUAL(0, result);
1279+
TEST_ASSERT(mock_output_contains("Disabled patch 0"));
1280+
}
1281+
1282+
void test_loader_cmd_enable_single_enable(void) {
1283+
setup_loader();
1284+
fl_init(&test_ctx);
1285+
1286+
/* First set up a patch */
1287+
const char* alloc_argv[] = {"fl", "--cmd", "alloc", "--size", "64"};
1288+
fl_exec_cmd(&test_ctx, 5, alloc_argv);
1289+
1290+
const char* patch_argv[]
1291+
= {"fl", "--cmd", "patch", "--comp", "0", "--orig", "0x08001000", "--target", "0x20000100"};
1292+
fl_exec_cmd(&test_ctx, 9, patch_argv);
1293+
1294+
/* Disable first */
1295+
const char* disable_argv[] = {"fl", "--cmd", "enable", "--comp", "0", "--enable", "0"};
1296+
fl_exec_cmd(&test_ctx, 7, disable_argv);
1297+
1298+
mock_output_reset();
1299+
1300+
/* Re-enable the patch */
1301+
const char* argv[] = {"fl", "--cmd", "enable", "--comp", "0", "--enable", "1"};
1302+
int result = fl_exec_cmd(&test_ctx, 7, argv);
1303+
1304+
TEST_ASSERT_EQUAL(0, result);
1305+
TEST_ASSERT(mock_output_contains("Enabled patch 0"));
1306+
}
1307+
1308+
void test_loader_cmd_enable_all_disable(void) {
1309+
setup_loader();
1310+
fl_init(&test_ctx);
1311+
1312+
/* Set up multiple patches */
1313+
const char* alloc_argv[] = {"fl", "--cmd", "alloc", "--size", "64"};
1314+
fl_exec_cmd(&test_ctx, 5, alloc_argv);
1315+
1316+
const char* patch0_argv[]
1317+
= {"fl", "--cmd", "patch", "--comp", "0", "--orig", "0x08001000", "--target", "0x20000100"};
1318+
fl_exec_cmd(&test_ctx, 9, patch0_argv);
1319+
1320+
fl_exec_cmd(&test_ctx, 5, alloc_argv);
1321+
const char* patch1_argv[]
1322+
= {"fl", "--cmd", "patch", "--comp", "1", "--orig", "0x08002000", "--target", "0x20000200"};
1323+
fl_exec_cmd(&test_ctx, 9, patch1_argv);
1324+
1325+
mock_output_reset();
1326+
1327+
/* Disable all patches */
1328+
const char* argv[] = {"fl", "--cmd", "enable", "--enable", "0", "--all"};
1329+
int result = fl_exec_cmd(&test_ctx, 6, argv);
1330+
1331+
TEST_ASSERT_EQUAL(0, result);
1332+
TEST_ASSERT(mock_output_contains("Disabled"));
1333+
TEST_ASSERT(mock_output_contains("patches"));
1334+
}
1335+
1336+
void test_loader_cmd_enable_all_enable(void) {
1337+
setup_loader();
1338+
fl_init(&test_ctx);
1339+
1340+
/* Set up multiple patches */
1341+
const char* alloc_argv[] = {"fl", "--cmd", "alloc", "--size", "64"};
1342+
fl_exec_cmd(&test_ctx, 5, alloc_argv);
1343+
1344+
const char* patch0_argv[]
1345+
= {"fl", "--cmd", "patch", "--comp", "0", "--orig", "0x08001000", "--target", "0x20000100"};
1346+
fl_exec_cmd(&test_ctx, 9, patch0_argv);
1347+
1348+
fl_exec_cmd(&test_ctx, 5, alloc_argv);
1349+
const char* patch1_argv[]
1350+
= {"fl", "--cmd", "patch", "--comp", "1", "--orig", "0x08002000", "--target", "0x20000200"};
1351+
fl_exec_cmd(&test_ctx, 9, patch1_argv);
1352+
1353+
/* Disable all first */
1354+
const char* disable_argv[] = {"fl", "--cmd", "enable", "--enable", "0", "--all"};
1355+
fl_exec_cmd(&test_ctx, 6, disable_argv);
1356+
1357+
mock_output_reset();
1358+
1359+
/* Re-enable all patches */
1360+
const char* argv[] = {"fl", "--cmd", "enable", "--enable", "1", "--all"};
1361+
int result = fl_exec_cmd(&test_ctx, 6, argv);
1362+
1363+
TEST_ASSERT_EQUAL(0, result);
1364+
TEST_ASSERT(mock_output_contains("Enabled"));
1365+
TEST_ASSERT(mock_output_contains("patches"));
1366+
}
1367+
1368+
void test_loader_cmd_enable_invalid_comp(void) {
1369+
setup_loader();
1370+
fl_init(&test_ctx);
1371+
1372+
/* Try to enable invalid comparator */
1373+
const char* argv[] = {"fl", "--cmd", "enable", "--comp", "99", "--enable", "1"};
1374+
int result = fl_exec_cmd(&test_ctx, 7, argv);
1375+
1376+
TEST_ASSERT(result != 0 || mock_output_contains("Invalid"));
1377+
}
1378+
1379+
void test_loader_cmd_enable_unset_patch(void) {
1380+
setup_loader();
1381+
fl_init(&test_ctx);
1382+
1383+
/* Try to enable a patch that was never set - should succeed but report 0 changed */
1384+
const char* argv[] = {"fl", "--cmd", "enable", "--comp", "0", "--enable", "1"};
1385+
int result = fl_exec_cmd(&test_ctx, 7, argv);
1386+
1387+
/* fpb_enable_patch returns FPB_ERR_NOT_SET for unset patches, so changed=0 */
1388+
TEST_ASSERT_EQUAL(0, result);
1389+
}
1390+
12441391
/* ============================================================================
12451392
* Test Runner
12461393
* ============================================================================ */
@@ -1351,4 +1498,14 @@ void run_loader_tests(void) {
13511498
RUN_TEST(test_loader_cmd_read_overflow_addr);
13521499
RUN_TEST(test_loader_cmd_write_force_hint_in_error);
13531500
TEST_SUITE_END();
1501+
1502+
TEST_SUITE_BEGIN("func_loader - Enable Command");
1503+
RUN_TEST(test_loader_cmd_enable_missing_arg);
1504+
RUN_TEST(test_loader_cmd_enable_single_disable);
1505+
RUN_TEST(test_loader_cmd_enable_single_enable);
1506+
RUN_TEST(test_loader_cmd_enable_all_disable);
1507+
RUN_TEST(test_loader_cmd_enable_all_enable);
1508+
RUN_TEST(test_loader_cmd_enable_invalid_comp);
1509+
RUN_TEST(test_loader_cmd_enable_unset_patch);
1510+
TEST_SUITE_END();
13541511
}

0 commit comments

Comments
 (0)