|
35 | 35 | #define CMD_NAND_DATA 0x22 |
36 | 36 | #define CMD_NAND_END 0x23 |
37 | 37 | #define CMD_NAND_MD5 0x24 |
| 38 | + |
| 39 | +#define CMD_EMMC_READ_CARD_INFO 0x41 |
| 40 | +#define CMD_EMMC_BEGIN 0x42 |
| 41 | +#define CMD_EMMC_DATA 0x43 |
| 42 | +#define CMD_EMMC_END 0x44 |
| 43 | +#define CMD_EMMC_MD5 0x45 |
| 44 | +#define CMD_EMMC_READ_DATA 0x46 |
| 45 | +#define CMD_EMMC_ERASE_DATA 0x47 |
| 46 | + |
38 | 47 | #define CMD_FLASH_ERASE_CHIP 0xD0 |
39 | 48 | #define CMD_FLASH_ERASE_REGION 0xD1 |
40 | 49 | #define CMD_READ_FLASH_ID 0xF3 |
@@ -648,3 +657,163 @@ cmd_change_baud(cskburn_serial_device_t *dev, uint32_t baud, uint32_t old_baud) |
648 | 657 |
|
649 | 658 | return 0; |
650 | 659 | } |
| 660 | + |
| 661 | +int |
| 662 | +cmd_emmc_get_info(cskburn_serial_device_t *dev, card_info_t *info) |
| 663 | +{ |
| 664 | + uint8_t ret_buf[STATUS_BYTES_LEN + sizeof(card_info_t)]; |
| 665 | + uint16_t ret_len = 0; |
| 666 | + |
| 667 | + int ret = command(dev, CMD_EMMC_READ_CARD_INFO, 0, CHECKSUM_NONE, NULL, ret_buf, &ret_len, |
| 668 | + sizeof(ret_buf), TIMEOUT_DEFAULT); |
| 669 | + |
| 670 | + if (ret != 0) { |
| 671 | + return ret; |
| 672 | + } |
| 673 | + |
| 674 | + if (ret_len < STATUS_BYTES_LEN) { |
| 675 | + LOGD("DEBUG: Interrupted serial read"); |
| 676 | + return -EIO; |
| 677 | + } |
| 678 | + |
| 679 | + if (ret_buf[0] != 0) { |
| 680 | + LOGD("DEBUG: Unexpected device response: 0x%02X", ret_buf[1]); |
| 681 | + return ret_buf[1]; |
| 682 | + } |
| 683 | + |
| 684 | + memcpy(info, ret_buf + STATUS_BYTES_LEN, sizeof(card_info_t)); |
| 685 | + |
| 686 | + return 0; |
| 687 | +} |
| 688 | + |
| 689 | +int |
| 690 | +cmd_emmc_begin(cskburn_serial_device_t *dev, uint32_t size, uint32_t blocks, uint32_t block_size, |
| 691 | + uint32_t offset) |
| 692 | +{ |
| 693 | + cmd_flash_begin_t *cmd = (cmd_flash_begin_t *)dev->req_cmd; |
| 694 | + memset(cmd, 0, sizeof(cmd_flash_begin_t)); |
| 695 | + cmd->size = size; |
| 696 | + cmd->blocks = blocks; |
| 697 | + cmd->block_size = block_size; |
| 698 | + cmd->offset = offset; |
| 699 | + |
| 700 | + return check_command( |
| 701 | + dev, CMD_EMMC_BEGIN, sizeof(cmd_flash_begin_t), CHECKSUM_NONE, NULL, TIMEOUT_DEFAULT); |
| 702 | +} |
| 703 | + |
| 704 | +int |
| 705 | +cmd_emmc_block(cskburn_serial_device_t *dev, uint8_t *data, uint32_t data_len, uint32_t seq) |
| 706 | +{ |
| 707 | + cmd_flash_block_t *cmd = (cmd_flash_block_t *)dev->req_cmd; |
| 708 | + memset(cmd, 0, sizeof(cmd_flash_block_t)); |
| 709 | + cmd->size = data_len; |
| 710 | + cmd->seq = seq; |
| 711 | + cmd->rev1 = 0; |
| 712 | + cmd->rev2 = 0; |
| 713 | + |
| 714 | + uint8_t *req_data = (uint8_t *)dev->req_cmd + sizeof(cmd_flash_block_t); |
| 715 | + memcpy(req_data, data, data_len); |
| 716 | + |
| 717 | + uint32_t in_len = sizeof(cmd_flash_block_t) + data_len; |
| 718 | + |
| 719 | + int ret = check_command( |
| 720 | + dev, CMD_EMMC_DATA, in_len, checksum(data, data_len), NULL, TIMEOUT_FLASH_DATA); |
| 721 | + |
| 722 | + if (ret != 0) { |
| 723 | + LOGD("DEBUG: Failed writing block %d", seq); |
| 724 | + } |
| 725 | + |
| 726 | + if (ret == 0x0A) { |
| 727 | + msleep(250); |
| 728 | + } |
| 729 | + |
| 730 | + return ret; |
| 731 | +} |
| 732 | + |
| 733 | +int |
| 734 | +cmd_emmc_finish(cskburn_serial_device_t *dev) |
| 735 | +{ |
| 736 | + cmd_flash_finish_t *cmd = (cmd_flash_finish_t *)dev->req_cmd; |
| 737 | + memset(cmd, 0, sizeof(cmd_flash_finish_t)); |
| 738 | + |
| 739 | + return check_command( |
| 740 | + dev, CMD_EMMC_END, sizeof(uint32_t), CHECKSUM_NONE, NULL, TIMEOUT_FLASH_END); |
| 741 | +} |
| 742 | + |
| 743 | +int |
| 744 | +cmd_emmc_erase_region(cskburn_serial_device_t *dev, uint32_t address, uint32_t size) |
| 745 | +{ |
| 746 | + cmd_flash_erase_t *cmd = (cmd_flash_erase_t *)dev->req_cmd; |
| 747 | + memset(cmd, 0, sizeof(cmd_flash_erase_t)); |
| 748 | + cmd->address = address; |
| 749 | + cmd->size = size; |
| 750 | + |
| 751 | + return check_command(dev, CMD_EMMC_ERASE_DATA, sizeof(cmd_flash_erase_t), CHECKSUM_NONE, NULL, |
| 752 | + calc_timeout(size, TIMEOUT_FLASH_ERASE_PER_MB)); |
| 753 | +} |
| 754 | + |
| 755 | +int |
| 756 | +cmd_emmc_md5(cskburn_serial_device_t *dev, uint32_t address, uint32_t size, uint8_t *md5) |
| 757 | +{ |
| 758 | + uint8_t ret_buf[STATUS_BYTES_LEN + 16]; |
| 759 | + uint16_t ret_len = 0; |
| 760 | + |
| 761 | + cmd_flash_md5_t *cmd = (cmd_flash_md5_t *)dev->req_cmd; |
| 762 | + memset(cmd, 0, sizeof(cmd_flash_md5_t)); |
| 763 | + cmd->address = address; |
| 764 | + cmd->size = size; |
| 765 | + |
| 766 | + int ret = command(dev, CMD_EMMC_MD5, sizeof(cmd_flash_md5_t), CHECKSUM_NONE, NULL, ret_buf, |
| 767 | + &ret_len, sizeof(ret_buf), calc_timeout(size, TIMEOUT_FLASH_MD5SUM_PER_MB)); |
| 768 | + if (ret != 0) { |
| 769 | + return ret; |
| 770 | + } |
| 771 | + |
| 772 | + if (ret_len < STATUS_BYTES_LEN) { |
| 773 | + LOGD("DEBUG: Interrupted serial read"); |
| 774 | + return -EIO; |
| 775 | + } |
| 776 | + |
| 777 | + if (ret_buf[0] != 0) { |
| 778 | + LOGD("DEBUG: Unexpected device response: 0x%02X", ret_buf[1]); |
| 779 | + return ret_buf[1]; |
| 780 | + } |
| 781 | + |
| 782 | + memcpy(md5, ret_buf + 2, 16); |
| 783 | + |
| 784 | + return 0; |
| 785 | +} |
| 786 | + |
| 787 | +int |
| 788 | +cmd_read_emmc(cskburn_serial_device_t *dev, uint32_t address, uint32_t size, uint8_t *data, |
| 789 | + uint32_t *data_len) |
| 790 | +{ |
| 791 | + static uint8_t ret_buf[STATUS_BYTES_LEN + FLASH_READ_SIZE]; |
| 792 | + uint16_t ret_len = 0; |
| 793 | + |
| 794 | + cmd_read_flash_t *cmd = (cmd_read_flash_t *)dev->req_cmd; |
| 795 | + memset(cmd, 0, sizeof(cmd_read_flash_t)); |
| 796 | + cmd->address = address; |
| 797 | + cmd->size = size; |
| 798 | + |
| 799 | + int ret = command(dev, CMD_EMMC_READ_DATA, sizeof(cmd_read_flash_t), CHECKSUM_NONE, NULL, |
| 800 | + ret_buf, &ret_len, sizeof(ret_buf), TIMEOUT_FLASH_DATA); |
| 801 | + if (ret != 0) { |
| 802 | + return ret; |
| 803 | + } |
| 804 | + |
| 805 | + if (ret_len < STATUS_BYTES_LEN) { |
| 806 | + LOGD("DEBUG: Interrupted serial read"); |
| 807 | + return -EIO; |
| 808 | + } |
| 809 | + |
| 810 | + if (ret_buf[0] != 0) { |
| 811 | + LOGD("DEBUG: Unexpected device response: 0x%02X", ret_buf[1]); |
| 812 | + return ret_buf[1]; |
| 813 | + } |
| 814 | + |
| 815 | + *data_len = ret_len - STATUS_BYTES_LEN; |
| 816 | + memcpy(data, ret_buf + STATUS_BYTES_LEN, *data_len); |
| 817 | + |
| 818 | + return 0; |
| 819 | +} |
0 commit comments