zhx 发表于 2026-5-2 15:44:47

写了一个flash模拟EEPROM 的程序,大家看看有没有漏洞

#ifndef _EEPROM_IAP_H_
#define _EEPROM_IAP_H_

/* ========= Flash 配置 ========= */
#define FLASH_BLOCK_SIZE    512
#define FLASH_START_ADDR    0x0000
#define FLASH_TOTAL_BLOCKS8

/* ========= EEPROM 配置 ========= */
#define EEPROM_META_SIZE    8
#define EEPROM_TOTAL_SIZE   3072   // 3KB 一页只用 504字节,要小于分配的Flash
#define EEPROM_PAGE_SIZE    (FLASH_BLOCK_SIZE - EEPROM_META_SIZE) //6字节页元数据,2个预留
#define EEPROM_PAGE_NUM   (EEPROM_TOTAL_SIZE / EEPROM_PAGE_SIZE)


/* ========= API ========= */
bitEEPROM_Init(void);
bitEEPROM_ReadByte(uint16_t addr, uint8_t *dat);
bitEEPROM_WriteByte(uint16_t addr, uint8_t dat);
bitEEPROM_Read(uint16_t addr, uint8_t *buf, uint16_t len);
bitEEPROM_Write(uint16_t addr, uint8_t *buf, uint16_t len);
bitEEPROM_Save(void);

#endif

#include "Config.h"

#include "eeprom_iap.h"

/* ========= 页缓存 ========= */
static uint8_t xdata page_buf;
static uint16_t cached_page = 0;
static bit page_dirty = 0;


/* ========= 页元数据 ========= */
typedef struct {
    uint16_t magic;
    uint16_t seq;
    uint16_t crc;
} FlashPageMeta;

/* ========= IAP 基础 ========= */
#define IAP_ENABLE()    IAP_CONTR = 0x80
#define IAP_DISABLE()   IAP_CONTR = 0x00
#define IAP_WAIT()      while (IAP_CONTR & 0x01)

static void Flash_EraseSector(uint16_t addr)
{
//EA = 0;
    IAP_TPS = 22;
    IAP_ENABLE();

    IAP_CMD = 0x03;
    IAP_ADDRH = addr >> 8;
    IAP_ADDRL = addr & 0xFF;
    IAP_TRIG = 0x5A;
    IAP_TRIG = 0xA5;
    IAP_WAIT();

    IAP_DISABLE();
//EA = 1;
}

static void Flash_WriteByte(uint16_t addr, uint8_t dat)
{
   // EA = 0;
    IAP_TPS = 22;
    IAP_ENABLE();

    IAP_CMD = 0x02;
    IAP_ADDRH = addr >> 8;
    IAP_ADDRL = addr & 0xFF;
    IAP_DATA = dat;
    IAP_TRIG = 0x5A;
    IAP_TRIG = 0xA5;
    IAP_WAIT();

    IAP_DISABLE();
//EA = 1;
}

static uint8_t Flash_ReadByte(uint16_t addr)
{
    uint8_t dat;
//EA = 0;
    IAP_TPS = 22;
    IAP_ENABLE();

    IAP_CMD = 0x01;
    IAP_ADDRH = addr >> 8;
    IAP_ADDRL = addr & 0xFF;
    IAP_TRIG = 0x5A;
    IAP_TRIG = 0xA5;
    IAP_WAIT();

    dat = IAP_DATA;
    IAP_DISABLE();
//EA = 1;
    return dat;
}

/* ========= CRC16 ========= */
static uint16_t CRC16(uint8_t *p, uint16_t len)
{
    uint16_t crc = 0xFFFF;
    uint16_t i, j;

    for (i = 0; i < len; i++) {
      crc ^= p;
      for (j = 0; j < 8; j++) {
            if (crc & 1)
                crc = (crc >> 1) ^ 0x8408;
            else
                crc >>= 1;
      }
    }
    return crc ^ 0xFFFF;
}

/* ========= 地址映射 ========= */
static uint16_t addr_to_page(uint16_t addr)
{
    return addr / EEPROM_PAGE_SIZE;
}

static uint16_t addr_to_offset(uint16_t addr)
{
    return addr % EEPROM_PAGE_SIZE;
}

static uint16_t page_to_flash(uint16_t page)
{
    return FLASH_START_ADDR + page * FLASH_BLOCK_SIZE;
}

/* ========= 页加载 ========= */
static bit load_page(uint16_t page)
{
    uint16_t i;
    uint16_t flash_addr = page_to_flash(page);
    FlashPageMeta meta;

    meta.magic = Flash_ReadByte(flash_addr + 0) << 8 | Flash_ReadByte(flash_addr + 1);
    meta.seq   = Flash_ReadByte(flash_addr + 2) << 8 | Flash_ReadByte(flash_addr + 3);
    meta.crc   = Flash_ReadByte(flash_addr + 4) << 8 | Flash_ReadByte(flash_addr + 5);

    if (meta.magic != 0x55AA) return 0;

    for (i = 0; i < EEPROM_PAGE_SIZE; i++)
      page_buf = Flash_ReadByte(flash_addr + EEPROM_META_SIZE + i);

    if (CRC16(page_buf, EEPROM_PAGE_SIZE) != meta.crc) return 0;

    cached_page = page;
    page_dirty = 0;
    return 1;
}

/* ========= 页保存 ========= */
static bit save_current_page(void)
{
    uint16_t i;
    uint16_t flash_addr;
    FlashPageMeta meta;
    if (page_dirty==1)//有修改
   {
       flash_addr = page_to_flash(cached_page);

       Flash_EraseSector(flash_addr);

       meta.magic = 0x55AA;
       meta.seq   = Flash_ReadByte(flash_addr + 2) << 8 | Flash_ReadByte(flash_addr + 3) + 1;
       meta.crc   = CRC16(page_buf, EEPROM_PAGE_SIZE);

       Flash_WriteByte(flash_addr + 0, meta.magic >> 8);
       Flash_WriteByte(flash_addr + 1, meta.magic & 0xFF);
       Flash_WriteByte(flash_addr + 2, meta.seq >> 8);
       Flash_WriteByte(flash_addr + 3, meta.seq & 0xFF);
       Flash_WriteByte(flash_addr + 4, meta.crc >> 8);
       Flash_WriteByte(flash_addr + 5, meta.crc & 0xFF);

       for (i = 0; i < EEPROM_PAGE_SIZE; i++)
          Flash_WriteByte(flash_addr + EEPROM_META_SIZE + i, page_buf);
       page_dirty=0;
       printf(" SAVE........\r\n");
   }
    return 1;
}

/* ========= 页切换保护 ========= */
static bit ensure_page(uint16_t page)
{
    if (cached_page == page) return 1;
    if (!save_current_page()) return 0;
    return load_page(page);
}

static bit is_empty_flash(void)
{
    uint16_t i;
    uint16_t addr;
    for (i = 0; i < EEPROM_PAGE_NUM; i++)
      {
      addr = page_to_flash(i);
      if (Flash_ReadByte(addr) != 0xFF || Flash_ReadByte(addr + 1) != 0xFF) return 0;
    }
    return 1;
}

static bit init_empty_eeprom(void)
{
    uint16_t i;
    uint16_t flash_addr = page_to_flash(0);
    FlashPageMeta meta;

    Flash_EraseSector(flash_addr);

    meta.magic = 0x55AA;
    meta.seq   = 1;
    meta.crc   = CRC16(page_buf, EEPROM_PAGE_SIZE);

    Flash_WriteByte(flash_addr + 0, meta.magic >> 8);
    Flash_WriteByte(flash_addr + 1, meta.magic & 0xFF);
    Flash_WriteByte(flash_addr + 2, meta.seq >> 8);
    Flash_WriteByte(flash_addr + 3, meta.seq & 0xFF);
    Flash_WriteByte(flash_addr + 4, meta.crc >> 8);
    Flash_WriteByte(flash_addr + 5, meta.crc & 0xFF);

    for (i = 0; i < EEPROM_PAGE_SIZE; i++)
      {
      Flash_WriteByte(flash_addr + EEPROM_META_SIZE + i, page_buf);
      }
    cached_page = 0;
    return 1;
}

/* ========= EEPROM API ========= */

bit EEPROM_Init(void)
{
    if (is_empty_flash())         // 首次使用
      {if(!init_empty_eeprom()) return 0;}
    // 正常加载
    if (!load_page(0)) return 0;
    return 1;
}

bit EEPROM_ReadByte(uint16_t addr, uint8_t *dat)
{
    if (addr >= EEPROM_TOTAL_SIZE) return 0;
    if (!ensure_page(addr_to_page(addr))) return 0;
    *dat = page_buf;
    return 1;
}

bit EEPROM_WriteByte(uint16_t addr, uint8_t dat)
{
   uint16_t page, offset;

    if (addr >= EEPROM_TOTAL_SIZE) return 0;

    page   = addr_to_page(addr);
    offset = addr_to_offset(addr);

    if (!ensure_page(page)) return 0;
    if (page_buf != dat)
      {
      page_buf = dat;
      page_dirty = 1;
      printf(">");
      }
    else
      printf(" ");

    printf("[%04X]:%02bX\r\n",addr,dat);

    return 1;
}

bit EEPROM_Read(uint16_t addr, uint8_t *buf, uint16_t len)
{
    uint16_t i;
    if (addr + len > EEPROM_TOTAL_SIZE) return 0;
    for (i = 0; i < len; i++)
      if (!EEPROM_ReadByte(addr + i, &buf)) return 0;
    return 1;
}

bit EEPROM_Write(uint16_t addr, uint8_t *buf, uint16_t len)
{
    uint16_t i;
    if (addr + len > EEPROM_TOTAL_SIZE) return 0;
    for (i = 0; i < len; i++)
      if (!EEPROM_WriteByte(addr + i, buf)) return 0;
    return 1;
}

bit EEPROM_Save(void)
{
   return save_current_page();
}
#ifndef __CONFIG_H__
#define __CONFIG_H__
#include <AI8H.h>
#include <def.h>
#include <stdio.h>
#include <intrins.h>
#include <string.h>
#include <stdarg.h>
#include <math.h>
#include <stdlib.h>
#endif大家看看有没有漏洞
页: [1]
查看完整版本: 写了一个flash模拟EEPROM 的程序,大家看看有没有漏洞