+       if (errors)
+               return usage_hf_mfu_info();
+
+       TagTypeUL_t tagtype = GetHF14AMfU_Type();
+       if (tagtype == UL_ERROR) {
+               return -1;
+       }
+
+       PrintAndLogEx(NORMAL, "\n--- Tag Information ---------");
+       PrintAndLogEx(NORMAL, "-------------------------------------------------------------");
+       ul_print_type(tagtype, 6);
+
+       // Swap endianness
+       if (swapEndian && hasAuthKey) 
+               authenticationkey = SwapEndian64(authenticationkey, keyLen, (keyLen == 16) ? 8 : 4 );
+
+       if (!ul_auth_select(&card, tagtype, hasAuthKey, authenticationkey, pack, sizeof(pack))) {
+               DropField();
+               return -1;
+       }
+
+       // read pages 0,1,2,3 (should read 4pages)
+       uint8_t data[16];
+       len = ul_read(0, data, sizeof(data));
+       if (len == -1) {
+               DropField();
+               PrintAndLogEx(WARNING, "Error: tag didn't answer to READ");
+               return -1;
+       } else if (len == 16) {
+               memcpy(uid, data, 3);
+               memcpy(uid+3, data+4, 4);
+               ul_print_default(data);
+               ndef_print_CC(data+12);
+       } else {
+               locked = true;
+       }
+
+       // UL_C Specific
+       if ((tagtype & UL_C)) {
+
+               // read pages 0x28, 0x29, 0x2A, 0x2B
+               uint8_t ulc_conf[16] = {0x00};
+               len = ul_read(0x28, ulc_conf, sizeof(ulc_conf));
+               if (len == -1) {
+                       DropField();
+                       PrintAndLogEx(WARNING, "Error: tag didn't answer to READ UL-C");
+                       return -1;
+               }
+               if (len == 16) {
+                       ulc_print_configuration(ulc_conf);
+               } else {
+                       locked = true;
+               }
+
+               if ((tagtype & MAGIC)) {
+                       //just read key
+                       uint8_t ulc_deskey[16] = {0x00};
+                       len = ul_read(0x2C, ulc_deskey, sizeof(ulc_deskey));
+                       if (len == -1) {
+                               DropField();
+                               PrintAndLogEx(WARNING, "Error: tag didn't answer to READ magic");
+                               return -1;
+                       }
+                       if (len == 16) ulc_print_3deskey(ulc_deskey);
+               } else {
+                       // if we called info with key, just return
+                       if (hasAuthKey) {
+                               DropField();
+                               return 1;
+                       }
+
+                       // also try to diversify default keys..  look into CmdHF14AMfuGenDiverseKeys
+                       PrintAndLogEx(INFO, "Trying some default 3des keys");
+                       for (uint8_t i = 0; i < KEYS_3DES_COUNT; ++i ) {
+                               uint8_t *key = default_3des_keys[i];
+                               if (ulc_authentication(key, true)) {
+                                       DropField();
+                                       PrintAndLogEx(SUCCESS, "Found default 3des key: ");
+                                       uint8_t keySwap[16];
+                                       memcpy(keySwap, SwapEndian64(key,16,8), 16);
+                                       ulc_print_3deskey(keySwap);
+                                       return 1;
+                               }
+                       }
+                       DropField();
+                       return 1;
+               }
+       }
+
+       // do counters and signature first (don't neet auth)
+
+       // ul counters are different than ntag counters
+       if ((tagtype & (UL_EV1_48 | UL_EV1_128))) {
+               if (ulev1_print_counters() != 3) {
+                       // failed - re-select
+                       if (!ul_auth_select( &card, tagtype, hasAuthKey, authenticationkey, pack, sizeof(pack))) {
+                               DropField();
+                               return -1;
+                       }
+               }
+       }
+
+       if ((tagtype & (UL_EV1_48 | UL_EV1_128 | NTAG_213 | NTAG_215 | NTAG_216 | NTAG_I2C_1K | NTAG_I2C_2K ))) {
+               uint8_t ulev1_signature[32] = {0x00};
+               len = ulev1_readSignature(ulev1_signature, sizeof(ulev1_signature));
+               if (len == -1) {
+                       DropField();
+                       PrintAndLogEx(WARNING, "Error: tag didn't answer to READ SIGNATURE");
+                       return -1;
+               }
+               if (len == 32) {
+                       ulev1_print_signature(tagtype, uid, ulev1_signature, sizeof(ulev1_signature));
+               } else {
+                       // re-select
+                       if (!ul_auth_select( &card, tagtype, hasAuthKey, authenticationkey, pack, sizeof(pack))) {
+                               DropField();
+                               return -1;
+                       }
+               }
+       }
+
+       if ((tagtype & (UL_EV1_48 | UL_EV1_128 | NTAG_210 | NTAG_212 | NTAG_213 | NTAG_215 | NTAG_216 | NTAG_I2C_1K | NTAG_I2C_2K))) {
+               uint8_t version[10] = {0x00};
+               len = ulev1_getVersion(version, sizeof(version));
+               if (len == -1) {
+                       DropField();
+                       PrintAndLogEx(WARNING, "Error: tag didn't answer to GETVERSION");
+                       return -1;
+               } else if (len == 10) {
+                       ulev1_print_version(version);
+               } else {
+                       locked = true;
+                       if (!ul_auth_select( &card, tagtype, hasAuthKey, authenticationkey, pack, sizeof(pack))) {
+                               DropField();
+                               return -1;
+                       }
+               }
+
+               uint8_t startconfigblock = 0;
+               uint8_t ulev1_conf[16] = {0x00};
+               // config blocks always are last 4 pages
+               for (uint8_t idx = 0; idx < MAX_UL_TYPES; idx++) {
+                       if (tagtype & UL_TYPES_ARRAY[idx]) {
+                               startconfigblock = UL_MEMORY_ARRAY[idx]-3;
+                               break;
+                       }
+               }
+
+               if (startconfigblock) { // if we know where the config block is...
+                       len = ul_read(startconfigblock, ulev1_conf, sizeof(ulev1_conf));
+                       if (len == -1) {
+                               DropField();
+                               PrintAndLogEx(WARNING, "Error: tag didn't answer to READ EV1");
+                               return -1;
+                       } else if (len == 16) {
+                               // save AUTHENTICATION LIMITS for later:
+                               authlim = (ulev1_conf[4] & 0x07);
+                               ulev1_print_configuration(ulev1_conf, startconfigblock);
+                       }
+               }
+
+               // AUTHLIMIT, (number of failed authentications)
+               // 0 = limitless.
+               // 1-7 = limit. No automatic tries then.
+               // hasAuthKey,  if we was called with key, skip test.
+               if (!authlim && !hasAuthKey) {
+                       PrintAndLogEx(NORMAL, "\n--- Known EV1/NTAG passwords.");
+                       len = 0;
+                       for (uint8_t i = 0; i < KEYS_PWD_COUNT; ++i ) {
+                               uint8_t *key = default_pwd_pack[i];
+                               len = ulev1_requestAuthentication(key, pack, sizeof(pack));
+                               if (len >= 1) {
+                                       PrintAndLogEx(SUCCESS, "Found a default password: %s || Pack: %02X %02X", sprint_hex(key, 4), pack[0], pack[1]);
+                                       break;
+                               } else {
+                                       if (!ul_auth_select( &card, tagtype, hasAuthKey, authenticationkey, pack, sizeof(pack))) {
+                                               DropField();
+                                               return -1;
+                                       }
+                               }
+                       }
+                       if (len < 1) PrintAndLogEx(WARNING, "password not known");
+               }
+       }
+
+       DropField();
+
+       if (locked) 
+               PrintAndLogEx(FAILED, "\nTag appears to be locked, try using the key to get more info");
+       PrintAndLogEx(NORMAL, "");
+
+       return 1;
+}
+
+//
+//  Write Single Block
+//
+static int usage_hf_mfu_wrbl(void) {
+       PrintAndLogEx(NORMAL, "Write a block. It autodetects card type.\n");
+       PrintAndLogEx(NORMAL, "Usage:  hf mfu wrbl b <block number> d <data> k <key> l\n");
+       PrintAndLogEx(NORMAL, "  Options:");
+       PrintAndLogEx(NORMAL, "  b <no>   : block to write");
+       PrintAndLogEx(NORMAL, "  d <data> : block data - (8 hex symbols)");
+       PrintAndLogEx(NORMAL, "  k <key>  : (optional) key for authentication [UL-C 16bytes, EV1/NTAG 4bytes]");
+       PrintAndLogEx(NORMAL, "  l        : (optional) swap entered key's endianness");
+       PrintAndLogEx(NORMAL, "");
+       PrintAndLogEx(NORMAL, "    sample : hf mfu wrbl b 0 d 01234567");
+       PrintAndLogEx(NORMAL, "           : hf mfu wrbl b 0 d 01234567 k AABBCCDDD\n");
+       return 0;
+}
+
+
+static int CmdHF14AMfUWrBl(const char *Cmd){
+
+       int blockNo = -1;
+       bool errors = false;
+       uint8_t keybytes[16] = {0x00};
+       uint8_t *authenticationkey = keybytes;
+       int keyLen = 0;
+       bool hasAuthKey = false;
+       bool swapEndian = false;
+       uint8_t cmdp = 0;
+       uint8_t blockdata[20] = {0x00};
+
+       while(param_getchar(Cmd, cmdp) != 0x00) {
+               switch(param_getchar(Cmd, cmdp)) {
+                       case 'h':
+                       case 'H':
+                               return usage_hf_mfu_wrbl();
+                       case 'k':
+                       case 'K':
+                               keyLen = 32;
+                               errors = param_gethex_ex(Cmd, cmdp+1, authenticationkey, &keyLen);
+                               if (errors || (keyLen != 32 && keyLen != 8)) { //ul-c or ev1/ntag key length
+                                       PrintAndLogEx(ERR, "Key has incorrect length.\n");
+                                       errors = true;
+                               }
+                               cmdp += 2;
+                               keyLen /= 2;
+                               hasAuthKey = true;
+                               break;
+                       case 'b':
+                       case 'B':
+                               blockNo = param_get8(Cmd, cmdp+1);
+                               if (blockNo < 0) {
+                                       PrintAndLogEx(ERR, "Wrong block number");
+                                       errors = true;
+                               }
+                               cmdp += 2;
+                               break;
+                       case 'l':
+                       case 'L':
+                               swapEndian = true;
+                               cmdp++;
+                               break;
+                       case 'd':
+                       case 'D':
+                               if ( param_gethex(Cmd, cmdp+1, blockdata, 8) ) {
+                                       PrintAndLogEx(ERR, "Block data must include 8 HEX symbols");
+                                       errors = true;
+                                       break;
+                               }
+                               cmdp += 2;
+                               break;
+                       default:
+                               PrintAndLogEx(ERR, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
+                               errors = true;
+                               break;
+               }
+               //Validations
+               if(errors) return usage_hf_mfu_wrbl();
+       }
+
+       if (blockNo == -1) return usage_hf_mfu_wrbl();
+       // starting with getting tagtype
+       TagTypeUL_t tagtype = GetHF14AMfU_Type();
+       if (tagtype == UL_ERROR) {
+               return -1;
+       }
+
+       uint8_t maxblockno = 0;
+       for (uint8_t idx = 0; idx < MAX_UL_TYPES; idx++) {
+               if (tagtype & UL_TYPES_ARRAY[idx]) {
+                       maxblockno = UL_MEMORY_ARRAY[idx];
+                       break;
+               }
+       }
+       if (blockNo > maxblockno){
+               DropField();
+               PrintAndLogEx(WARNING, "block number too large. Max block is %u/0x%02X \n", maxblockno,maxblockno);
+               return usage_hf_mfu_wrbl();
+       }
+
+       // Swap endianness
+       if (swapEndian && hasAuthKey) authenticationkey = SwapEndian64(authenticationkey, keyLen, (keyLen == 16) ? 8 : 4);
+
+       if ( blockNo <= 3)
+               PrintAndLogEx(NORMAL, "Special Block: %0d (0x%02X) [ %s]", blockNo, blockNo, sprint_hex(blockdata, 4));
+       else
+               PrintAndLogEx(NORMAL, "Block: %0d (0x%02X) [ %s]", blockNo, blockNo, sprint_hex(blockdata, 4));
+
+       //Send write Block
+       UsbCommand c = {CMD_MIFAREU_WRITEBL, {blockNo}};
+       memcpy(c.d.asBytes, blockdata, 4);
+
+       if (hasAuthKey) {
+               c.arg[1] = (keyLen == 16) ? 1 : 2;
+               memcpy(c.d.asBytes+4, authenticationkey, keyLen);
+       }
+
+       clearCommandBuffer();
+       SendCommand(&c);
+       UsbCommand resp;
+       if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
+               uint8_t isOK  = resp.arg[0] & 0xff;
+               PrintAndLogEx(SUCCESS, "isOk:%02x", isOK);
+       } else {
+               PrintAndLogEx(ERR, "Command execute timeout");
+       }
+
+       DropField();
+       return 0;
+}
+
+
+//
+//  Read Single Block
+//
+static int usage_hf_mfu_rdbl(void) {
+       PrintAndLogEx(NORMAL, "Read a block and print. It autodetects card type.\n");
+       PrintAndLogEx(NORMAL, "Usage:  hf mfu rdbl b <block number> k <key> l\n");
+       PrintAndLogEx(NORMAL, "  Options:");
+       PrintAndLogEx(NORMAL, "  b <no>  : block to read");
+       PrintAndLogEx(NORMAL, "  k <key> : (optional) key for authentication [UL-C 16bytes, EV1/NTAG 4bytes]");
+       PrintAndLogEx(NORMAL, "  l       : (optional) swap entered key's endianness");
+       PrintAndLogEx(NORMAL, "");
+       PrintAndLogEx(NORMAL, "   sample : hf mfu rdbl b 0");
+       PrintAndLogEx(NORMAL, "          : hf mfu rdbl b 0 k 00112233445566778899AABBCCDDEEFF");
+       PrintAndLogEx(NORMAL, "          : hf mfu rdbl b 0 k AABBCCDDD\n");
+       return 0;
+}
+
+
+static int CmdHF14AMfURdBl(const char *Cmd){
+
+       int blockNo = -1;
+       bool errors = false;
+       uint8_t keybytes[16] = {0x00};
+       uint8_t *authenticationkey = keybytes;
+       int keyLen = 0;
+       bool hasAuthKey = false;
+       bool swapEndian = false;
+       uint8_t cmdp = 0;
+
+       while(param_getchar(Cmd, cmdp) != 0x00)