sim: re-structure how we support cards + applications

Before this change, a card application (USIM, ISIM, ...) didn't
exist as a separate concept from a card profile.  This meant,
we had a manual combination of UICC card profile with USIM application,
and another one of UICC card profile and ISIM application.  But what
if there's a combined USIM+ISIM?

In reality, applications exist as separate objects, on top of an
ETSI UICC.  Lets therefore register all known applications to the
osim library core, and add code to osmo-sim-test which dynamically
detects all applications present on a given card (by reading EF.DIR).

Change-Id: Ic4b4ac433a9976842b30a017fb0fc347d87201cd
diff --git a/src/sim/card_fs_uicc.c b/src/sim/card_fs_uicc.c
index af6061c..c73fc9a 100644
--- a/src/sim/card_fs_uicc.c
+++ b/src/sim/card_fs_uicc.c
@@ -1,7 +1,7 @@
 /*! \file card_fs_uicc.c
  * ETSI UICC specific structures / routines. */
 /*
- * (C) 2012 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2012-2020 by Harald Welte <laforge@gnumonks.org>
  *
  * All Rights Reserved
  *
@@ -25,8 +25,12 @@
 
 
 #include <osmocom/sim/sim.h>
+#include <osmocom/core/talloc.h>
 #include <osmocom/gsm/tlv.h>
 
+#include "sim_int.h"
+#include "gsm_int.h"
+
 /* TS 102 221 V10.0.0 / 10.2.1 */
 const struct osim_card_sw ts102221_uicc_sw[] = {
 	{
@@ -171,6 +175,23 @@
 	OSIM_CARD_SW_LAST
 };
 
+static const struct osim_card_sw *uicc_card_sws[] = {
+	ts102221_uicc_sw,
+	NULL
+};
+
+/* TS 102 221 Chapter 13.1 */
+static const struct osim_file_desc uicc_ef_in_mf[] = {
+	EF_LIN_FIX_N(0x2f00, SFI_NONE, "EF.DIR", 0, 1, 32,
+			"Application directory"),
+	EF_TRANSP_N(0x2FE2, SFI_NONE, "EF.ICCID", 0, 10, 10,
+			"ICC Identification"),
+	EF_TRANSP_N(0x2F05, SFI_NONE, "EF.PL", 0, 2, 20,
+			"Preferred Languages"),
+	EF_LIN_FIX_N(0x2F06, SFI_NONE, "EF.ARR", F_OPTIONAL, 1, 256,
+			"Access Rule Reference"),
+};
+
 const struct value_string ts102221_fcp_vals[14] = {
 	{ UICC_FCP_T_FCP,		"File control parameters" },
 	{ UICC_FCP_T_FILE_SIZE,		"File size" },
@@ -209,3 +230,30 @@
 
 /* Annex E - TS 101 220 */
 static const uint8_t __attribute__((__unused__)) adf_uicc_aid[] = { 0xA0, 0x00, 0x00, 0x00, 0x87, 0x10, 0x01 };
+
+struct osim_card_profile *osim_cprof_uicc(void *ctx)
+{
+	struct osim_card_profile *cprof;
+	struct osim_file_desc *mf;
+	int rc;
+
+	cprof = talloc_zero(ctx, struct osim_card_profile);
+	cprof->name = "3GPP UICC";
+	cprof->sws = uicc_card_sws; // FIXME: extend later
+
+	mf = alloc_df(cprof, 0x3f00, "MF");
+
+	cprof->mf = mf;
+
+	/* Core UICC Files */
+	add_filedesc(mf, uicc_ef_in_mf, ARRAY_SIZE(uicc_ef_in_mf));
+
+	/* DF.TELECOM hierarchy as sub-directory of MF */
+	rc = osim_int_cprof_add_telecom(mf);
+	if (rc != 0) {
+		talloc_free(cprof);
+		return NULL;
+	}
+
+	return cprof;
+}