summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Klug <john.klug@multitech.com>2023-01-11 12:33:38 -0600
committerJohn Klug <john.klug@multitech.com>2023-01-11 12:33:38 -0600
commit96c6d98e3988e5926dcc57ac50b1f496d8c41008 (patch)
tree2fc36a7650b73561db795870774095329f05a707
parentbafffd9fc4ffd9a4624c2133483aa5842dd80ff6 (diff)
parent2915166559ea8ac70b515414ac0b2a86438b22f9 (diff)
downloadmts-id-eeprom-master.tar.gz
mts-id-eeprom-master.tar.bz2
mts-id-eeprom-master.zip
MTCDT3 EEPROM changesHEAD0.6.7master
-rw-r--r--src/eeprom_main.c206
1 files changed, 177 insertions, 29 deletions
diff --git a/src/eeprom_main.c b/src/eeprom_main.c
index 66c948b..d2199a0 100644
--- a/src/eeprom_main.c
+++ b/src/eeprom_main.c
@@ -33,6 +33,7 @@
#include <mts-kernel-headers/linux/mts_eeprom.h>
#ifdef MTCDT3B
#include <mts-kernel-headers/linux/mtcdt3b_eeprom.h>
+#include <mts-kernel-headers/linux/mtcdt3dc_eeprom.h>
#endif
#include "log.h"
@@ -47,6 +48,7 @@ static void mts_ap_eeprom_inspect(struct mts_ap_eeprom_layout *ap_eeprom);
#ifdef MTCDT3B
static void mtcdt3b_eeprom_inspect(struct mtcdt3b_eeprom_layout *mtcdt3b_eeprom);
+static void mtcdt3dc_eeprom_inspect(struct mtcdt3dc_eeprom_layout *mtcdt3dc_eeprom);
#endif
//Returns 0 on success, 1 on failure
@@ -173,6 +175,7 @@ static int id_yaml_out(const char *name, struct mts_id_eeprom_layout *id_eeprom)
fprintf(file, "capa-battery: %s\n", DEVICE_CAPA(id_eeprom->capa, CAPA_BATTERY) ? "true" : "false");
fprintf(file, "capa-supercap: %s\n", DEVICE_CAPA(id_eeprom->capa, CAPA_SUPERCAP) ? "true" : "false");
fprintf(file, "capa-cellular: %s\n", DEVICE_CAPA(id_eeprom->capa, CAPA_CELLULAR) ? "true" : "false");
+ fprintf(file, "capa-user-data-encryption: %s\n", DEVICE_CAPA(id_eeprom->capa, CAPA_USER_DATA_ENCRYPTION) ? "true" : "false");
fprintf(file, "capa: \"");
for (i = 0; i < sizeof(id_eeprom->capa); i++) {
@@ -305,9 +308,6 @@ static int mtcdt3b_yaml_out(const char *name, struct mtcdt3b_eeprom_layout *mtcd
mtcdt3b_eeprom->mac_addr[3],
mtcdt3b_eeprom->mac_addr[4],
mtcdt3b_eeprom->mac_addr[5]);
- fprintf(file, "capa-lora: %s\n", DEVICE_CAPA(mtcdt3b_eeprom->capa, MTCDT3B_CAPA_LORA) ? "true" : "false");
- fprintf(file, "lora-product-id: \"%.32s\"\n", mtcdt3b_eeprom->lora_product_id);
- fprintf(file, "lora-hw-version: \"%.32s\"\n", mtcdt3b_eeprom->lora_hw_version);
for(i=0;i<2;i++) {
fprintf(file,"slot %d:\n",i);
fprintf(file, " lora-device-id: \"%.32s\"\n", mtcdt3b_eeprom->slot[i].device_id);
@@ -322,8 +322,8 @@ static int mtcdt3b_yaml_out(const char *name, struct mtcdt3b_eeprom_layout *mtcd
mtcdt3b_eeprom->slot[i].lora_eui[7]);
}
fprintf(file, "capa-eth-switch: %s\n", DEVICE_CAPA(mtcdt3b_eeprom->capa, MTCDT3B_CAPA_ETH_SWITCH) ? "true" : "false");
- fprintf(file, "hw-version-eth-switch: %hu\n", mtcdt3b_eeprom->hw_version_eth_switch);
- fprintf(file, "mac-eth-switch: \"%02X:%02X:%02X:%02X:%02X:%02X\"\n",
+ fprintf(file, "eth-switch-version: %hu\n", mtcdt3b_eeprom->hw_version_eth_switch);
+ fprintf(file, "eth-switch-mac-addr: \"%02X:%02X:%02X:%02X:%02X:%02X\"\n",
mtcdt3b_eeprom->mac_eth_switch[0],
mtcdt3b_eeprom->mac_eth_switch[1],
mtcdt3b_eeprom->mac_eth_switch[2],
@@ -336,6 +336,39 @@ static int mtcdt3b_yaml_out(const char *name, struct mtcdt3b_eeprom_layout *mtcd
return 0;
}
+
+static int mtcdt3dc_yaml_out(const char *name, struct mtcdt3dc_eeprom_layout *mtcdt3dc_eeprom)
+{
+ FILE *file;
+
+ if (!strcmp(name, "-")) {
+ file = stdout;
+ } else {
+ file = fopen(name, "w+");
+ if (!file) {
+ log_error("could not open %s: %m", name);
+ return -1;
+ }
+ }
+
+ fprintf(file, "---\n");
+ fprintf(file, "\n");
+ fprintf(file, "vendor-id: \"%.32s\"\n", mtcdt3dc_eeprom->vendor_id);
+ fprintf(file, "product-id: \"%.32s\"\n", mtcdt3dc_eeprom->product_id);
+ fprintf(file, "device-id: \"%.32s\"\n", mtcdt3dc_eeprom->device_id);
+ fprintf(file, "hw-version: \"%.32s\"\n", mtcdt3dc_eeprom->hw_version);
+ fprintf(file, "capa-mei-serial: %.32s\n", DEVICE_CAPA(mtcdt3dc_eeprom->capa, MTCDT3DC_CAPA_SERIAL) ? "true" : "false");
+ fprintf(file, "capa-mtac: %.32s\n", DEVICE_CAPA(mtcdt3dc_eeprom->capa, MTCDT3DC_CAPA_MTAC) ? "true" : "false");
+ fprintf(file, "mei-serial-count: %hu\n", mtcdt3dc_eeprom->serial_cnt);
+ fprintf(file, "mtac-count: %hu\n", mtcdt3dc_eeprom->mtac_cnt);
+
+ fprintf(file, "...\n");
+ fclose(file);
+
+ return 0;
+
+}
+
#endif
static int bin_out(const char *name, char *eeprom)
@@ -397,6 +430,7 @@ static void mts_id_eeprom_inspect(struct mts_id_eeprom_layout *id_eeprom)
log_info("capa-lora-lbt: %s", DEVICE_CAPA(id_eeprom->capa, CAPA_LORA_LBT) ? "yes" : "no");
log_info("capa-supercap: %s", DEVICE_CAPA(id_eeprom->capa, CAPA_SUPERCAP) ? "yes" : "no");
log_info("capa-cellular: %s", DEVICE_CAPA(id_eeprom->capa, CAPA_CELLULAR) ? "yes" : "no");
+ log_info("capa-user-data-encryption: %s", DEVICE_CAPA(id_eeprom->capa, CAPA_USER_DATA_ENCRYPTION) ? "yes" : "no");
log_info("mac-bluetooth: %02X:%02X:%02X:%02X:%02X:%02X",
id_eeprom->mac_bluetooth[0],
@@ -488,9 +522,6 @@ static void mtcdt3b_eeprom_inspect(struct mtcdt3b_eeprom_layout *mtcdt3b_eeprom)
mtcdt3b_eeprom->mac_addr[3],
mtcdt3b_eeprom->mac_addr[4],
mtcdt3b_eeprom->mac_addr[5]);
- log_info("mtcdt3b-capa-lora: %s", DEVICE_CAPA(mtcdt3b_eeprom->capa, MTCDT3B_CAPA_LORA) ? "yes" : "no");
- log_info("lora-product-id: %.32s", mtcdt3b_eeprom->lora_product_id);
- log_info("lora-hw-version: %.32s", mtcdt3b_eeprom->lora_hw_version);
for(i=0;i<2;i++) {
log_info("slot %d:",i);
log_info(" lora-device-id: \"%.32s\"", mtcdt3b_eeprom->slot[i].device_id);
@@ -505,8 +536,8 @@ static void mtcdt3b_eeprom_inspect(struct mtcdt3b_eeprom_layout *mtcdt3b_eeprom)
mtcdt3b_eeprom->slot[i].lora_eui[7]);
}
log_info("capa-eth-switch: %s", DEVICE_CAPA(mtcdt3b_eeprom->capa, MTCDT3B_CAPA_ETH_SWITCH) ? "yes" : "no");
- log_info("hw-version-eth-switch: %hu", mtcdt3b_eeprom->hw_version_eth_switch);
- log_info("mac-eth-switch: \"%02X:%02X:%02X:%02X:%02X:%02X\"",
+ log_info("eth-switch-version: %hu", mtcdt3b_eeprom->hw_version_eth_switch);
+ log_info("eth-switch-mac-addr: \"%02X:%02X:%02X:%02X:%02X:%02X\"",
mtcdt3b_eeprom->mac_eth_switch[0],
mtcdt3b_eeprom->mac_eth_switch[1],
mtcdt3b_eeprom->mac_eth_switch[2],
@@ -514,6 +545,18 @@ static void mtcdt3b_eeprom_inspect(struct mtcdt3b_eeprom_layout *mtcdt3b_eeprom)
mtcdt3b_eeprom->mac_eth_switch[4],
mtcdt3b_eeprom->mac_eth_switch[5]);
}
+
+static void mtcdt3dc_eeprom_inspect(struct mtcdt3dc_eeprom_layout *mtcdt3dc_eeprom)
+{
+ log_info("vendor-id: %.32s", mtcdt3dc_eeprom->vendor_id);
+ log_info("product-id: %.32s", mtcdt3dc_eeprom->product_id);
+ log_info("device-id: %.32s", mtcdt3dc_eeprom->device_id);
+ log_info("hw-version: %.32s", mtcdt3dc_eeprom->hw_version);
+ log_info("capa-mei-serial: %.32s", DEVICE_CAPA(mtcdt3dc_eeprom->capa, MTCDT3DC_CAPA_MTAC) ? "true" : "false");
+ log_info("capa-mtac: %.32s", DEVICE_CAPA(mtcdt3dc_eeprom->capa, MTCDT3DC_CAPA_SERIAL) ? "true" : "false");
+ log_info("mei-serial count: %hu", mtcdt3dc_eeprom->serial_cnt);
+ log_info("mtac count: %hu", mtcdt3dc_eeprom->mtac_cnt);
+}
#endif
static void print_version(const char *name) {
@@ -558,6 +601,7 @@ static void usage(FILE *out) {
fprintf(out, " --capa-battery |\n");
fprintf(out, " --capa-supercap |\n");
fprintf(out, " --capa-cellular |\n");
+ fprintf(out, " --capa-user-data-encryption |\n");
fprintf(out, " --capa-clear (clears all flags) |\n");
fprintf(out, " --hex-to-bin | \n");
fprintf(out, " --out-format { bin | yaml (default) } |\n");
@@ -565,8 +609,13 @@ static void usage(FILE *out) {
fprintf(out, " --accessory-card\n");
#ifdef MTCDT3B
fprintf(out, " --base-board\n");
+ fprintf(out, " --daughter-board\n");
fprintf(out, " --slot i=0,device-id=<device-id>,lora-eui=<EUI-64>,i=1,...\n");
fprintf(out, " --capa-eth-switch \n");
+ fprintf(out, " --capa-mtac \n");
+ fprintf(out, " --capa-serial \n");
+ fprintf(out, " --mtac-count <mtac-count> \n");
+ fprintf(out, " --serial-count <serial-count> \n");
fprintf(out, " --eth-switch-version <switch-version> \n");
fprintf(out, " --eth-switch-mac-addr <switch-mac-addr> \n");
#endif
@@ -600,6 +649,7 @@ enum {
CMD_OPT_CAPA_BATTERY,
CMD_OPT_CAPA_SUPERCAP,
CMD_OPT_CAPA_CELLULAR,
+ CMD_OPT_CAPA_USER_DATA_ENCRYPTION,
CMD_OPT_CAPA_CLEAR,
CMD_OPT_OUT_FORMAT,
CMD_OPT_UPDATE,
@@ -610,10 +660,15 @@ enum {
#endif
#ifdef MTCDT3B
CMD_OPT_BASE_BOARD,
+ CMD_OPT_DAUGHTER_BOARD,
CMD_OPT_SLOTS,
CMD_OPT_CAPA_ETH_SWITCH,
CMD_OPT_ETH_SWITCH_VERSION,
CMD_OPT_ETH_SWITCH_MAC_ADDR,
+ CMD_OPT_CAPA_MTAC,
+ CMD_OPT_CAPA_SERIAL,
+ CMD_OPT_NUM_MTAC,
+ CMD_OPT_NUM_SERIAL,
#endif
CMD_OPT_VERSION,
CMD_OPT_HELP,
@@ -651,6 +706,7 @@ static struct option long_options[] = {
{"capa-battery", 0, NULL, CMD_OPT_CAPA_BATTERY},
{"capa-supercap", 0, NULL, CMD_OPT_CAPA_SUPERCAP},
{"capa-cellular", 0, NULL, CMD_OPT_CAPA_CELLULAR},
+ {"capa-user-data-encryption", 0, NULL, CMD_OPT_CAPA_USER_DATA_ENCRYPTION},
{"capa-clear", 0, NULL, CMD_OPT_CAPA_CLEAR},
{"hex-to-bin", 0, NULL, CMD_OPT_HEX_TO_BIN},
{"out-format", 1, NULL, CMD_OPT_OUT_FORMAT},
@@ -658,8 +714,13 @@ static struct option long_options[] = {
{"accessory-card", 0, NULL, CMD_OPT_ACCESSORY_CARD},
#ifdef MTCDT3B
{"base-board", 0, NULL, CMD_OPT_BASE_BOARD},
+ {"daughter-board", 0, NULL, CMD_OPT_DAUGHTER_BOARD},
{"slots", 1, NULL, CMD_OPT_SLOTS},
{"capa-eth-switch", 0, NULL, CMD_OPT_CAPA_ETH_SWITCH},
+ {"capa-mtac", 0, NULL, CMD_OPT_CAPA_MTAC},
+ {"capa-serial", 0, NULL, CMD_OPT_CAPA_SERIAL},
+ {"mtac-count", 1, NULL, CMD_OPT_NUM_MTAC},
+ {"serial-count", 1, NULL, CMD_OPT_NUM_SERIAL},
{"eth-switch-version", 1, NULL, CMD_OPT_ETH_SWITCH_VERSION},
{"eth-switch-mac-addr", 1, NULL, CMD_OPT_ETH_SWITCH_MAC_ADDR},
#endif
@@ -694,6 +755,7 @@ int main(int argc, char *argv[]) {
int accessory_card = 0;
#ifdef MTCDT3B
int base_board = 0;
+ int daughter_board = 0;
char *slots = NULL;
#endif
char *vendor_id = NULL;
@@ -719,6 +781,14 @@ int main(int argc, char *argv[]) {
eeprom_size,sizeof mtcdt3b_eeprom);
exit(1);
}
+
+ struct mtcdt3dc_eeprom_layout mtcdt3dc_eeprom;
+ memset (&mtcdt3dc_eeprom, 0, eeprom_size);
+ if (sizeof mtcdt3dc_eeprom != eeprom_size) {
+ fprintf(stderr, "Internal error:\n mtcdt3dc_eeprom is not the correct size: expected %d, but %d is defined for the part\n",
+ eeprom_size,sizeof mtcdt3dc_eeprom);
+ exit(1);
+ }
#endif
memset(&id_eeprom, 0, eeprom_size);
@@ -742,6 +812,10 @@ int main(int argc, char *argv[]) {
case CMD_OPT_BASE_BOARD:
base_board = 1;
break;
+
+ case CMD_OPT_DAUGHTER_BOARD:
+ daughter_board = 1;
+ break;
#endif
case CMD_OPT_VERSION:
@@ -768,10 +842,13 @@ int main(int argc, char *argv[]) {
if (accessory_card) {
tmp = read(fd, (char *) &ap_eeprom, eeprom_size);
#ifdef MTCDT3B
- } else if (base_board) {
- tmp = read(fd, (char *) &mtcdt3b_eeprom, eeprom_size);
+ } else if (base_board) {
+ tmp = read(fd, (char *) &mtcdt3b_eeprom, eeprom_size);
+
+ } else if (daughter_board) {
+ tmp = read(fd, (char *) &mtcdt3dc_eeprom, eeprom_size);
#endif
- } else {
+ } else {
tmp = read(fd, (char *) &id_eeprom, eeprom_size);
}
@@ -787,11 +864,13 @@ int main(int argc, char *argv[]) {
log_info("loaded ap eeprom from %s successfully", in_file);
mts_ap_eeprom_inspect(&ap_eeprom);
#ifdef MTCDT3B
- } else if (base_board) {
+ } else if (base_board) {
log_info("loaded ap eeprom from %s successfully", in_file);
mtcdt3b_eeprom_inspect(&mtcdt3b_eeprom);
+ } else if (daughter_board) {
+ mtcdt3dc_eeprom_inspect(&mtcdt3dc_eeprom);
#endif
- } else {
+ } else {
log_info("loaded id eeprom from %s successfully", in_file);
mts_id_eeprom_inspect(&id_eeprom);
}
@@ -823,6 +902,11 @@ int main(int argc, char *argv[]) {
case CMD_OPT_BASE_BOARD:
// handled above
break;
+
+ case CMD_OPT_DAUGHTER_BOARD:
+ // handled above
+ break;
+
case CMD_OPT_SLOTS:
// concatenate slots arguments
if (base_board) {
@@ -964,17 +1048,25 @@ int main(int argc, char *argv[]) {
break;
case CMD_OPT_CAPA_LORA:
-#ifdef MTCDT3B
- if (base_board) {
- DEVICE_CAPA_SET(mtcdt3b_eeprom.capa, MTCDT3B_CAPA_LORA);
- break;
- }
-#endif
DEVICE_CAPA_SET(id_eeprom.capa, CAPA_LORA);
break;
+#ifdef MTCDT3B
+ case CMD_OPT_CAPA_MTAC:
+ if (daughter_board) {
+ DEVICE_CAPA_SET(mtcdt3dc_eeprom.capa, MTCDT3DC_CAPA_MTAC);
+ }
+ break;
+
+ case CMD_OPT_CAPA_SERIAL:
+ if (daughter_board) {
+ DEVICE_CAPA_SET(mtcdt3dc_eeprom.capa, MTCDT3DC_CAPA_SERIAL);
+ }
+ break;
+#endif
case CMD_OPT_CAPA_LORA_LBT:
DEVICE_CAPA_SET(id_eeprom.capa, CAPA_LORA_LBT);
break;
+
case CMD_OPT_CAPA_BATTERY:
DEVICE_CAPA_SET(id_eeprom.capa, CAPA_BATTERY);
break;
@@ -987,6 +1079,10 @@ int main(int argc, char *argv[]) {
DEVICE_CAPA_SET(id_eeprom.capa, CAPA_CELLULAR);
break;
+ case CMD_OPT_CAPA_USER_DATA_ENCRYPTION:
+ DEVICE_CAPA_SET(id_eeprom.capa, CAPA_USER_DATA_ENCRYPTION);
+ break;
+
case CMD_OPT_CAPA_CLEAR:
capa_clear = 1;
break;
@@ -1048,6 +1144,39 @@ int main(int argc, char *argv[]) {
}
}
break;
+ case CMD_OPT_NUM_MTAC:
+ if (daughter_board) {
+ uint16_t u16_mtac_test;
+ if (sscanf(optarg, "%hu", &u16_mtac_test) != 1) {
+ log_error("invalid mtac count %s", optarg);
+ usage(stderr);
+ exit(1);
+ }
+ if (u16_mtac_test < MTAC_MIN || u16_mtac_test >MTAC_MAX) {
+ log_error("invalid mtac count %s", optarg);
+ usage(stderr);
+ exit(1);
+ }
+ mtcdt3dc_eeprom.mtac_cnt = u16_mtac_test;
+ }
+ break;
+
+ case CMD_OPT_NUM_SERIAL:
+ if (daughter_board) {
+ uint16_t u16_serial_test;
+ if (sscanf(optarg, "%hu", &u16_serial_test) !=1) {
+ log_error("invalid serial count %s", optarg);
+ usage(stderr);
+ exit(1);
+ }
+ if (u16_serial_test < SERIAL_MIN || u16_serial_test > SERIAL_MAX) {
+ log_error("invalid serial count %s", optarg);
+ usage(stderr);
+ exit(1);
+ }
+ mtcdt3dc_eeprom.serial_cnt = u16_serial_test;
+ }
+ break;
#endif
default:
usage(stderr);
@@ -1060,6 +1189,11 @@ int main(int argc, char *argv[]) {
memset(mtcdt3b_eeprom.capa, 0, sizeof(mtcdt3b_eeprom.capa));
capa_clear = 0;
}
+
+ if(daughter_board && capa_clear) {
+ memset(mtcdt3dc_eeprom.capa, 0, sizeof(mtcdt3dc_eeprom.capa));
+ capa_clear = 0;
+ }
#endif
if(capa_clear) {
@@ -1077,6 +1211,9 @@ int main(int argc, char *argv[]) {
#ifdef MTCDT3B
else if (base_board)
EEPROM_SET(mtcdt3b_eeprom,vendor_id)
+
+ else if (daughter_board)
+ EEPROM_SET(mtcdt3dc_eeprom,vendor_id)
#endif
else
EEPROM_SET(id_eeprom,vendor_id)
@@ -1087,6 +1224,10 @@ int main(int argc, char *argv[]) {
#ifdef MTCDT3B
else if (base_board)
EEPROM_SET(mtcdt3b_eeprom,product_id)
+
+ else if (daughter_board)
+ EEPROM_SET(mtcdt3dc_eeprom,product_id)
+
#endif
else
EEPROM_SET(id_eeprom,product_id)
@@ -1097,6 +1238,9 @@ int main(int argc, char *argv[]) {
#ifdef MTCDT3B
else if (base_board)
EEPROM_SET(mtcdt3b_eeprom,device_id)
+ else if (daughter_board)
+ EEPROM_SET(mtcdt3dc_eeprom,device_id)
+
#endif
else
EEPROM_SET(id_eeprom,device_id)
@@ -1107,6 +1251,9 @@ int main(int argc, char *argv[]) {
#ifdef MTCDT3B
else if (base_board)
EEPROM_SET(mtcdt3b_eeprom,hw_version)
+ else if (daughter_board)
+ EEPROM_SET(mtcdt3dc_eeprom,hw_version)
+
#endif
else
EEPROM_SET(id_eeprom,hw_version)
@@ -1135,10 +1282,6 @@ int main(int argc, char *argv[]) {
usage(stderr);
exit(1);
}
-#ifdef MTCDT3B
- else if (base_board)
- EEPROM_SET(mtcdt3b_eeprom,lora_product_id)
-#endif
else
EEPROM_SET(id_eeprom,lora_product_id)
}
@@ -1150,10 +1293,6 @@ int main(int argc, char *argv[]) {
usage(stderr);
exit(1);
}
-#ifdef MTCDT3B
- else if (base_board)
- EEPROM_SET(mtcdt3b_eeprom,lora_hw_version)
-#endif
else
EEPROM_SET(id_eeprom,lora_hw_version)
}
@@ -1295,6 +1434,9 @@ int main(int argc, char *argv[]) {
#ifdef MTCDT3B
else if (base_board)
bin_out(out_file, (char*) &mtcdt3b_eeprom);
+
+ else if (daughter_board)
+ bin_out(out_file, (char*) &mtcdt3dc_eeprom);
#endif
else {
id_eeprom.eeprom_layout_version = EEPROM_LAYOUT_VERSION;
@@ -1306,6 +1448,9 @@ int main(int argc, char *argv[]) {
#ifdef MTCDT3B
else if (base_board)
mtcdt3b_yaml_out(out_file, &mtcdt3b_eeprom);
+
+ else if (daughter_board)
+ mtcdt3dc_yaml_out(out_file, &mtcdt3dc_eeprom);
#endif
else
id_yaml_out(out_file, &id_eeprom);
@@ -1322,6 +1467,9 @@ int main(int argc, char *argv[]) {
#ifdef MTCDT3B
else if (base_board)
mtcdt3b_eeprom_inspect(&mtcdt3b_eeprom);
+
+ else if (daughter_board)
+ mtcdt3dc_eeprom_inspect(&mtcdt3dc_eeprom);
#endif
else
mts_id_eeprom_inspect(&id_eeprom);