---
title: Partition Management
description: ESP partition table creation, customization, and analysis tools
---

import { Aside, Tabs, TabItem } from '@astrojs/starlight/components';

The Partition Manager component provides 3 tools for generating and analyzing ESP partition tables. Partition tables define how flash memory is divided into regions for bootloader, application code, OTA slots, NVS storage, and filesystems.

Partition tables are stored at flash offset `0x8000` and occupy up to `0xC00` (3072) bytes. The tools in this component generate CSV-format tables compatible with ESP-IDF's `gen_esp32part.py` tool.

---

## esp_partition_create_ota

Generate an OTA-capable partition table with two application slots, NVS storage, OTA data, and PHY calibration data. Follows Espressif's recommended OTA layout. Any remaining flash space is allocated to a SPIFFS storage partition.

### Parameters

| Name | Type | Default | Description |
|------|------|---------|-------------|
| `flash_size` | `str` | `"4MB"` | Total flash size. Accepts values like `"4MB"`, `"8MB"`, `"16MB"`. |
| `app_size` | `str` | `"1MB"` | Size for each OTA application slot. Accepts values like `"1MB"`, `"1536K"`. |

### Generated Layout

The tool produces the following partition structure (sizes shown for 4MB flash, 1MB app slots):

| Partition | Type | Subtype | Offset | Size |
|-----------|------|---------|--------|------|
| `nvs` | data | nvs | 0x9000 | 24KB |
| `otadata` | data | ota | 0xf000 | 8KB |
| `phy_init` | data | phy | 0x11000 | 4KB |
| `ota_0` | app | ota_0 | 0x12000 | 1MB |
| `ota_1` | app | ota_1 | 0x112000 | 1MB |
| `storage` | data | spiffs | 0x212000 | (remaining) |

### Example

```python
result = await client.call_tool("esp_partition_create_ota", {
    "flash_size": "4MB",
    "app_size": "1MB"
})
```

### Return Value

```json
{
  "success": true,
  "flash_size": "4MB",
  "app_size": "1MB",
  "partition_csv": "# ESP-IDF Partition Table (OTA layout)\n# Name, Type, SubType, Offset, Size, Flags\nnvs, data, nvs, 0x9000, 24KB,\n...",
  "partitions": [
    {"name": "nvs", "type": "data", "subtype": "nvs", "offset": "0x9000", "size": "24KB"},
    {"name": "otadata", "type": "data", "subtype": "ota", "offset": "0xf000", "size": "8KB"},
    {"name": "phy_init", "type": "data", "subtype": "phy", "offset": "0x11000", "size": "4KB"},
    {"name": "ota_0", "type": "app", "subtype": "ota_0", "offset": "0x12000", "size": "1MB"},
    {"name": "ota_1", "type": "app", "subtype": "ota_1", "offset": "0x112000", "size": "1MB"},
    {"name": "storage", "type": "data", "subtype": "spiffs", "offset": "0x212000", "size": "1984KB"}
  ],
  "space_remaining": "1984KB",
  "note": "Flash this CSV with gen_esp32part.py to binary, then write to 0x8000"
}
```

The tool returns an error if the requested layout does not fit within the specified flash size.

---

## esp_partition_custom

Create a custom partition table from a configuration dictionary. Offsets are auto-calculated starting from `0x9000` if not explicitly provided. App-type partitions are automatically aligned to 64KB boundaries.

### Parameters

| Name | Type | Default | Description |
|------|------|---------|-------------|
| `partition_config` | `dict` | *(required)* | Configuration with a `"partitions"` key containing a list of partition entries. |

Each partition entry supports these fields:

| Key | Type | Required | Description |
|-----|------|----------|-------------|
| `name` | `str` | Yes | Partition name (max 15 characters). |
| `type` | `str` | Yes | `"app"` or `"data"`. |
| `subtype` | `str` | Yes | Subtype name (see reference tables below). |
| `size` | `str` | Yes | Partition size (e.g., `"64K"`, `"1MB"`, `"0x10000"`). |
| `offset` | `str` | No | Explicit hex offset. Auto-calculated if omitted. |

### Example

```python
result = await client.call_tool("esp_partition_custom", {
    "partition_config": {
        "partitions": [
            {"name": "nvs", "type": "data", "subtype": "nvs", "size": "24K"},
            {"name": "factory", "type": "app", "subtype": "factory", "size": "1MB"},
            {"name": "storage", "type": "data", "subtype": "littlefs", "size": "512K"}
        ]
    }
})
```

### Return Value

```json
{
  "success": true,
  "partition_csv": "# ESP-IDF Partition Table (custom layout)\n# Name, Type, SubType, Offset, Size, Flags\nnvs, data, nvs, 0x9000, 24KB,\nfactory, app, factory, 0x10000, 1MB,\nstorage, data, littlefs, 0x110000, 512KB,\n",
  "partitions": [
    {"name": "nvs", "type": "data", "subtype": "nvs", "offset": "0x9000", "size": "24KB"},
    {"name": "factory", "type": "app", "subtype": "factory", "offset": "0x10000", "size": "1MB"},
    {"name": "storage", "type": "data", "subtype": "littlefs", "offset": "0x110000", "size": "512KB"}
  ],
  "total_size": "1560KB",
  "note": "Flash this CSV with gen_esp32part.py to binary, then write to 0x8000"
}
```

Validation errors are returned per-partition:

```json
{
  "success": false,
  "errors": [
    "Partition 'badpart': invalid subtype 'unknown' (use: ['ota', 'phy', 'nvs', ...])"
  ]
}
```

---

## esp_partition_analyze

Read and parse the partition table from a connected device. Reads 3072 bytes from flash offset `0x8000`, then decodes the 32-byte binary entries into a structured table.

Works with both physical devices and QEMU virtual devices.

### Parameters

| Name | Type | Default | Description |
|------|------|---------|-------------|
| `port` | `str \| None` | `None` | Serial port or `socket://` URI. **Required** -- returns error if omitted. |

### Example

```python
result = await client.call_tool("esp_partition_analyze", {
    "port": "/dev/ttyUSB0"
})
```

### Return Value

```json
{
  "success": true,
  "port": "/dev/ttyUSB0",
  "partition_count": 6,
  "partitions": [
    {
      "name": "nvs",
      "type": "data",
      "subtype": "nvs",
      "offset": "0x9000",
      "size": "24KB",
      "size_bytes": 24576,
      "encrypted": false
    },
    {
      "name": "ota_0",
      "type": "app",
      "subtype": "ota_0",
      "offset": "0x10000",
      "size": "1MB",
      "size_bytes": 1048576,
      "encrypted": false
    }
  ]
}
```

If the flash is blank or erased, the tool returns an empty partition list:

```json
{
  "success": true,
  "port": "/dev/ttyUSB0",
  "partitions": [],
  "note": "No valid partition entries found (flash may be blank or erased)"
}
```

### Binary Format

Each partition table entry is 32 bytes:

| Offset | Size | Field |
|--------|------|-------|
| 0 | 2 bytes | Magic number (`0xAA50` little-endian) |
| 2 | 1 byte | Type |
| 3 | 1 byte | Subtype |
| 4 | 4 bytes | Offset (little-endian) |
| 8 | 4 bytes | Size (little-endian) |
| 12 | 16 bytes | Name (null-terminated ASCII) |
| 28 | 4 bytes | Flags (bit 0 = encrypted) |

Entries with magic `0xFFFF` indicate the end of the table (erased flash).

---

## Partition Type Reference

### App Subtypes

| Subtype | Value | Description |
|---------|-------|-------------|
| `factory` | `0x00` | Factory application. Boot target when no OTA data exists. |
| `ota_0` | `0x10` | OTA slot 0. |
| `ota_1` | `0x11` | OTA slot 1. |
| `ota_2` | `0x12` | OTA slot 2. |
| `ota_3` | `0x13` | OTA slot 3. |
| `test` | `0x20` | Test application. Boot target when GPIO test mode is selected. |

### Data Subtypes

| Subtype | Value | Description |
|---------|-------|-------------|
| `ota` | `0x00` | OTA selection data. Tracks which OTA slot is active. |
| `phy` | `0x01` | PHY calibration data. |
| `nvs` | `0x02` | Non-volatile storage (key-value pairs). |
| `coredump` | `0x03` | Core dump storage for post-mortem debugging. |
| `nvs_keys` | `0x04` | NVS encryption keys. |
| `efuse` | `0x05` | eFuse emulation data. |
| `fat` | `0x81` | FAT filesystem. |
| `spiffs` | `0x82` | SPIFFS filesystem. |
| `littlefs` | `0x83` | LittleFS filesystem. |

### Size Format

The `size` parameter accepts several formats:

| Format | Example | Bytes |
|--------|---------|-------|
| Megabytes | `"1MB"`, `"4M"` | 1048576, 4194304 |
| Kilobytes | `"64K"`, `"24KB"` | 65536, 24576 |
| Hex | `"0x10000"` | 65536 |
| Decimal | `"4096"` | 4096 |

<Aside type="tip">
App-type partitions must be aligned to 64KB (0x10000) boundaries. The custom partition tool handles this automatically by rounding up the offset when needed.
</Aside>
