esp32/bootloader/bootloader.c
bool load_partition_table(bootloader_state_t* bs, uint32_t addr)
{
    partition_info_t partition;
    uint32_t end = addr + 0x1000;
    int index = 0;
    char *partition_usage;

    ESP_LOGI(TAG, "Partition Table:");
    ESP_LOGI(TAG, "## Label            Usage          Type ST Offset   Length");

    while (addr < end) {
        ESP_LOGD(TAG, "load partition table entry from %x(%08x)", addr, (uint32_t)MEM_CACHE(addr));
        memcpy(&partition, MEM_CACHE(addr), sizeof(partition));
        ESP_LOGD(TAG, "type=%x subtype=%x", partition.type, partition.subtype);
        partition_usage = "unknown";

        if (partition.magic == PARTITION_MAGIC) { /* valid partition definition */
            switch(partition.type) {
            case PART_TYPE_APP: /* app partition */
                switch(partition.subtype) {
                case PART_SUBTYPE_FACTORY: /* factory binary */
                    bs->image[0] = partition.pos;
                    partition_usage = "factory app";
                    bs->image_count = 1;
                    break;
                default:
                    /* OTA binary */
                    if ((partition.subtype & ~PART_SUBTYPE_OTA_MASK) == PART_SUBTYPE_OTA_FLAG) {
                        bs->image[bs->image_count++] = partition.pos;
                        partition_usage = "OTA app";
                    } else {
                        partition_usage = "Unknown app";
                    }
                    break;
                }
                break; /* PART_TYPE_APP */
            case PART_TYPE_DATA: /* data partition */
                switch(partition.subtype) {
                case PART_SUBTYPE_DATA_OTA: /* ota data */
                    bs->ota_info = partition.pos;
                    partition_usage = "OTA data";
                    break;
                case PART_SUBTYPE_DATA_RF:
                    partition_usage = "RF data";
                    break;
                case PART_SUBTYPE_DATA_WIFI:
                    partition_usage = "WiFi data";
                    break;
                default:
                    partition_usage = "Unknown data";
                    break;
                }
                break; /* PARTITION_USAGE_DATA */
            default: /* other partition type */
                break;
            }
        }
        /* invalid partition magic number */
        else {
            break; /* todo: validate md5 */
        }

        /* print partition type info */
        ESP_LOGI(TAG, "%2d %-16s %-16s %02x %02x %08x %08x", index, partition.label, partition_usage,
                 partition.type, partition.subtype,
                 partition.pos.offset, partition.pos.size);
        index++;
        addr += sizeof(partition);
    }

    ESP_LOGI(TAG,"End of partition table");
    return true;
}
/**
 *  @function :     load_partition_table
 *  @description:   Parse partition table, get useful data such as location of 
 *                  OTA info sector, factory app sector, and test app sector.
 *
 *  @inputs:        bs     bootloader state structure used to save the data
 *                  addr   address of partition table in flash
 *  @return:        return true, if the partition table is loaded (and MD5 checksum is valid)
 *
 */
@function :     load_partition_table
@description:   Parse partition table, get useful data such as location of
OTA info sector, factory app sector, and test app sector.

@inputs:        bs     bootloader state structure used to save the data
addr   address of partition table in flash
@return:        return true, if the partition table is loaded (and MD5 checksum is valid)
@function : load_partition_table @description : Parse partition table get useful data such as location of OTA info sector factory app sector and test app sector . @inputs : bs bootloader state structure used to save the data addr address of partition table in flash @return : return true if the partition table is loaded ( and MD5 checksum is valid )
bool load_partition_table(bootloader_state_t* bs, uint32_t addr)
{
    partition_info_t partition;
    uint32_t end = addr + 0x1000;
    int index = 0;
    char *partition_usage;
    ESP_LOGI(TAG, "Partition Table:");
    ESP_LOGI(TAG, "## Label            Usage          Type ST Offset   Length");
    while (addr < end) {
        ESP_LOGD(TAG, "load partition table entry from %x(%08x)", addr, (uint32_t)MEM_CACHE(addr));
        memcpy(&partition, MEM_CACHE(addr), sizeof(partition));
        ESP_LOGD(TAG, "type=%x subtype=%x", partition.type, partition.subtype);
        partition_usage = "unknown";
        if (partition.magic == PARTITION_MAGIC) { 
            switch(partition.type) {
            case PART_TYPE_APP: 
                switch(partition.subtype) {
                case PART_SUBTYPE_FACTORY: 
                    bs->image[0] = partition.pos;
                    partition_usage = "factory app";
                    bs->image_count = 1;
                    break;
                default:
                    if ((partition.subtype & ~PART_SUBTYPE_OTA_MASK) == PART_SUBTYPE_OTA_FLAG) {
                        bs->image[bs->image_count++] = partition.pos;
                        partition_usage = "OTA app";
                    } else {
                        partition_usage = "Unknown app";
                    }
                    break;
                }
                break; 
            case PART_TYPE_DATA: 
                switch(partition.subtype) {
                case PART_SUBTYPE_DATA_OTA: 
                    bs->ota_info = partition.pos;
                    partition_usage = "OTA data";
                    break;
                case PART_SUBTYPE_DATA_RF:
                    partition_usage = "RF data";
                    break;
                case PART_SUBTYPE_DATA_WIFI:
                    partition_usage = "WiFi data";
                    break;
                default:
                    partition_usage = "Unknown data";
                    break;
                }
                break; 
            default: 
                break;
            }
        }
        else {
            break; 
        }
        ESP_LOGI(TAG, "%2d %-16s %-16s %02x %02x %08x %08x", index, partition.label, partition_usage,
                 partition.type, partition.subtype,
                 partition.pos.offset, partition.pos.size);
        index++;
        addr += sizeof(partition);
    }
    ESP_LOGI(TAG,"End of partition table");
    return true;
}
bool load_partition_table ( bootloader_state_t * bs , uint32_t addr ) { partition_info_t partition ; uint32_t end = addr + 0x1000 ; int index = 0 ; char * partition_usage ; ESP_LOGI ( TAG , " " ) ; ESP_LOGI ( TAG , " " ) ; while ( addr < end ) { ESP_LOGD ( TAG , " " , addr , ( uint32_t ) MEM_CACHE ( addr ) ) ; memcpy ( & partition , MEM_CACHE ( addr ) , sizeof ( partition ) ) ; ESP_LOGD ( TAG , " " , partition . type , partition . subtype ) ; partition_usage = " " ; if ( partition . magic == PARTITION_MAGIC ) { switch ( partition . type ) { case PART_TYPE_APP : switch ( partition . subtype ) { case PART_SUBTYPE_FACTORY : bs -> image [ 0 ] = partition . pos ; partition_usage = " " ; bs -> image_count = 1 ; break ; default : if ( ( partition . subtype & ~ PART_SUBTYPE_OTA_MASK ) == PART_SUBTYPE_OTA_FLAG ) { bs -> image [ bs -> image_count ++ ] = partition . pos ; partition_usage = " " ; } else { partition_usage = " " ; } break ; } break ; case PART_TYPE_DATA : switch ( partition . subtype ) { case PART_SUBTYPE_DATA_OTA : bs -> ota_info = partition . pos ; partition_usage = " " ; break ; case PART_SUBTYPE_DATA_RF : partition_usage = " " ; break ; case PART_SUBTYPE_DATA_WIFI : partition_usage = " " ; break ; default : partition_usage = " " ; break ; } break ; default : break ; } } else { break ; } ESP_LOGI ( TAG , " " , index , partition . label , partition_usage , partition . type , partition . subtype , partition . pos . offset , partition . pos . size ) ; index ++ ; addr += sizeof ( partition ) ; } ESP_LOGI ( TAG , " " ) ; return true ; }
@function :     load_partition_table
  @description:   Parse partition table, get useful data such as location of
                  OTA info sector, factory app sector, and test app sector.
@function : load_partition_table @description : Parse partition table get useful data such as location of OTA info sector factory app sector and test app sector .
/* valid partition definition */ /* app partition */ /* factory binary */ /* OTA binary */ /* PART_TYPE_APP */ /* data partition */ /* ota data */ /* PARTITION_USAGE_DATA */ /* other partition type */ /* invalid partition magic number */ /* todo: validate md5 */ /* print partition type info */