Skip to content

Commit

Permalink
Got the NAND working a bit more
Browse files Browse the repository at this point in the history
  • Loading branch information
devos50 committed Feb 12, 2023
1 parent 999255e commit fa67c82
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 11 deletions.
61 changes: 56 additions & 5 deletions hw/arm/ipod_touch_fmss.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,46 @@
static void write_chip_info(IPodTouchFMSSState *s)
{
uint32_t chipid[] = { 0xb614d5ad, 0xb614d5ad, 0xb614d5ad, 0xb614d5ad };
cpu_physical_memory_write(s->reg_target_addr, &chipid, 0x10);
cpu_physical_memory_write(s->reg_cinfo_target_addr, &chipid, 0x10);
}

static void read_nand_pages(IPodTouchFMSSState *s)
{
for(int page_ind = 0; page_ind < s->reg_num_pages; page_ind++) {
uint32_t page_nr = 0;
uint32_t page_out_addr = 0;
uint32_t page_spare_out_addr = 0;
cpu_physical_memory_read(s->reg_pages_in_addr + page_ind, &page_nr, 0x4);
cpu_physical_memory_read(s->reg_pages_out_addr + page_ind, &page_out_addr, 0x4);
if(page_nr == 524160) {
// NAND signature page
uint8_t *page = calloc(0x100, sizeof(uint8_t));
char *magic = "NANDDRIVERSIGN";
memcpy(page, magic, strlen(magic));
page[0x34] = 0x4; // length of the info

// signature (0x43313131)
page[0x38] = 0x31;
page[0x39] = 0x31;
page[0x3A] = 0x31;
page[0x3B] = 0x43;
printf("Will read page %d into address 0x%08x\n", page_nr, page_out_addr);
cpu_physical_memory_write(page_out_addr, page, 0x100);
}
else if(page_nr == 524161) {
// BBT page
uint8_t *page = calloc(0x100, sizeof(uint8_t));
char *magic = "DEVICEINFOBBT";
memcpy(page, magic, strlen(magic));
cpu_physical_memory_write(page_out_addr, page, 0x100);
}

// write the spare
printf("Writing spare to 0x%08x\n", s->reg_page_spare_out_addr);
uint8_t *spare = calloc(0x10, sizeof(uint8_t));
spare[9] = 0x80;
cpu_physical_memory_write(s->reg_page_spare_out_addr, spare, 0x10);
}
}

static uint64_t ipod_touch_fmss_read(void *opaque, hwaddr addr, unsigned size)
Expand Down Expand Up @@ -38,12 +77,24 @@ static void ipod_touch_fmss_write(void *opaque, hwaddr addr, uint64_t val, unsig
case FMSS__CS_IRQ:
if(val == 0xD) { s->reg_cs_irq_bit = 0; } // clear interrupt bit
break;
case FMSS_TARGET_ADDR:
s->reg_target_addr = val;
case FMSS_CINFO_TARGET_ADDR:
s->reg_cinfo_target_addr = val;
write_chip_info(s);
break;
case FMSS_PAGES_IN_ADDR:
s->reg_pages_in_addr = val;
break;
case FMSS_NUM_PAGES:
s->reg_num_pages = val;
break;
case FMSS_PAGE_SPARE_OUT_ADDR:
s->reg_page_spare_out_addr = val;
break;
case FMSS_CMD: // I assume this is a CMD register??
if(val == 0x8) { write_chip_info(s); }
case FMSS_PAGES_OUT_ADDR:
s->reg_pages_out_addr = val;
break;
case 0xD38:
read_nand_pages(s);
}
}

Expand Down
19 changes: 13 additions & 6 deletions include/hw/arm/ipod_touch_fmss.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,26 @@
#define TYPE_IPOD_TOUCH_FMSS "ipodtouch.fmss"
OBJECT_DECLARE_SIMPLE_TYPE(IPodTouchFMSSState, IPOD_TOUCH_FMSS)

#define FMSS__FMCTRL1 0x4
#define FMSS__CS_IRQ 0xC0C
#define FMSS__CS_BUF_RST_OK 0xC64
#define FMSS_TARGET_ADDR 0xD08
#define FMSS_CMD 0xD0C
#define FMSS__FMCTRL1 0x4
#define FMSS__CS_IRQ 0xC0C
#define FMSS__CS_BUF_RST_OK 0xC64
#define FMSS_CINFO_TARGET_ADDR 0xD08
#define FMSS_PAGES_IN_ADDR 0xD0C
#define FMSS_NUM_PAGES 0xD18
#define FMSS_PAGE_SPARE_OUT_ADDR 0xD1C
#define FMSS_PAGES_OUT_ADDR 0xD20

typedef struct IPodTouchFMSSState
{
SysBusDevice parent_obj;
MemoryRegion iomem;
qemu_irq irq;
uint32_t reg_cs_irq_bit;
uint32_t reg_target_addr;
uint32_t reg_cinfo_target_addr;
uint32_t reg_pages_in_addr;
uint32_t reg_num_pages;
uint32_t reg_page_spare_out_addr;
uint32_t reg_pages_out_addr;
} IPodTouchFMSSState;

#endif

2 comments on commit fa67c82

@lemonjesus
Copy link

@lemonjesus lemonjesus commented on fa67c82 Feb 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might find the research I've done on the S5L8702's FMSS layer to be useful - I assume the M2 FMSS layer also uses some sort of state machine bytecode to do the work of communicating with the flash chip. There might be some differences, but I assume it's closer than what you might have found "published" about other chips (like the H2). I'm working on expanding the NAND flash capability of the iPod Nano 3G which uses the S5L8702, so if you discover something useful about this peripheral and its underlying bytecode, please let me know. I've taken a break on that project but I want to get back into it and study it more.

https://github.com/lemonjesus/S5L8702-FMISS-Tools

@devos50
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lemonjesus thank you so much for linking this! It's indeed the M2 that I'm targeting as this is also referenced in the decompiled code. I already reverse-engineered a few registers here and there, but your documentation might be very helpful in further understanding its architecture.

Having said that, I haven't looked that deep into the specific meanings of every register yet and mostly hacked some things together on a lazy Sunday afternoon 😅. It looks however that the higher levels (the FTL/VFL layer) are similar to what I already reverse-engineered for the iPod Touch 1G, and I do have full source code for these aspects. 👍

Please sign in to comment.