SHT30 온습도 모니터링 시스템 전체 소스(서버 PHP, STM32 펌웨어, SQL, 테스트). 전체 코드리뷰에서 도출된 보안 하드닝 10건 반영: - 요청 서명 HMAC-SHA256 전환(펌웨어 sig.c/서버 config.php/호스트 패리티 동시) - 재전송 방어 + 기본 API_KEY fail-closed + 디바이스 문자열 정제(api/sensor_data.php) - 오프라인 SMS 중복 발송 경합 제거(cron_heartbeat.php, 원자적 선점) - CSV 수식 주입 방지(monthly_report.php), 감사로그 회전 락(retention_cleanup.php) - 브루트포스 카운터 원자화(login.php), 예시 TOTP 비밀키 무효화, 마이그레이션 멱등화 _backup/(하드코딩 실 비밀값 포함)·config.local.php·런타임 상태는 .gitignore 제외.
182 lines
5.9 KiB
Text
182 lines
5.9 KiB
Text
/* =============================================================================
|
|
* STM32F407VGTx_FLASH.ld - GNU ld 링커 스크립트 (ST 스타일)
|
|
*
|
|
* 대상: STM32F407VGT6 (Cortex-M4F)
|
|
* FLASH 1024K @ 0x08000000 (코드/상수/초기화 데이터 원본)
|
|
* RAM 128K @ 0x20000000 (SRAM1+SRAM2, .data/.bss/heap/stack)
|
|
* CCMRAM 64K @ 0x10000000 (Core-Coupled Memory; DMA 접근 불가)
|
|
*
|
|
* CCMRAM 활용(중요):
|
|
* CCMRAM 은 코어 전용 64K 버스로 데이터 접근 지연이 적다(코드 페치 불가,
|
|
* DMA/이더넷 DMA 디스크립터/버퍼 사용 불가). 핫한 비-DMA 데이터를 두기에 좋다.
|
|
* - FreeRTOS heap_4 의 ucHeap 을 CCMRAM 에 두려면 heap_4.c 가 참조하는
|
|
* 배열에 __attribute__((section(".ccmram"))) 를 부여하거나, configAPPLICATION_
|
|
* ALLOCATED_HEAP=1 로 두고 사용자 정의 ucHeap[] 를 .ccmram 에 배치한다.
|
|
* - 특정 태스크 스택을 CCMRAM 에 두려면 static StackType_t 배열에
|
|
* section(".ccmram") 를 지정하고 xTaskCreateStatic() 으로 생성한다.
|
|
* 주의: LwIP/ETH DMA 버퍼는 절대 CCMRAM 에 두지 말 것(이더넷 DMA 비접근).
|
|
* ===========================================================================*/
|
|
|
|
/* 진입점(startup_stm32f407xx.s 의 리셋 핸들러). */
|
|
ENTRY(Reset_Handler)
|
|
|
|
/* ── 스택/힙 최소 크기 (startup 어셈블리/sbrk 가 참조) ───────────────────── */
|
|
/* _estack: 메인 스택 포인터 초기값(RAM 최상단). 인터럽트/스케줄러 시작 전 사용. */
|
|
_Min_Heap_Size = 0x400; /* newlib malloc/sbrk 최소 힙 (FreeRTOS 는 자체 힙 사용) */
|
|
_Min_Stack_Size = 0x800; /* 메인/인터럽트 스택 최소 (2K) */
|
|
|
|
/* ── 메모리 영역 ─────────────────────────────────────────────────────────── */
|
|
MEMORY
|
|
{
|
|
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
|
|
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
|
|
CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K
|
|
}
|
|
|
|
/* RAM 최상단을 메인 스택 초기 포인터로 사용. */
|
|
_estack = ORIGIN(RAM) + LENGTH(RAM);
|
|
|
|
/* ── 섹션 배치 ───────────────────────────────────────────────────────────── */
|
|
SECTIONS
|
|
{
|
|
/* 1) 인터럽트 벡터 테이블 — 플래시 선두(0x08000000). */
|
|
.isr_vector :
|
|
{
|
|
. = ALIGN(4);
|
|
KEEP(*(.isr_vector)) /* startup 의 벡터 테이블 (가비지 컬렉션 금지) */
|
|
. = ALIGN(4);
|
|
} >FLASH
|
|
|
|
/* 2) 코드 (.text). */
|
|
.text :
|
|
{
|
|
. = ALIGN(4);
|
|
*(.text)
|
|
*(.text*)
|
|
*(.glue_7) /* ARM/Thumb 인터워킹 glue */
|
|
*(.glue_7t)
|
|
*(.eh_frame)
|
|
KEEP(*(.init))
|
|
KEEP(*(.fini))
|
|
. = ALIGN(4);
|
|
_etext = .; /* 코드 끝 */
|
|
} >FLASH
|
|
|
|
/* 3) 읽기 전용 데이터 (.rodata: const, 문자열, CA PEM 등). */
|
|
.rodata :
|
|
{
|
|
. = ALIGN(4);
|
|
*(.rodata)
|
|
*(.rodata*)
|
|
. = ALIGN(4);
|
|
} >FLASH
|
|
|
|
/* ARM 예외 처리 인덱스(EHABI). nano/nosys 에서도 링크 정합성을 위해 유지. */
|
|
.ARM.extab :
|
|
{
|
|
. = ALIGN(4);
|
|
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
|
. = ALIGN(4);
|
|
} >FLASH
|
|
|
|
.ARM :
|
|
{
|
|
. = ALIGN(4);
|
|
__exidx_start = .;
|
|
*(.ARM.exidx*)
|
|
__exidx_end = .;
|
|
. = ALIGN(4);
|
|
} >FLASH
|
|
|
|
/* C++ / libc 초기화 배열(preinit/init/fini). startup 이 호출. */
|
|
.preinit_array :
|
|
{
|
|
. = ALIGN(4);
|
|
PROVIDE_HIDDEN(__preinit_array_start = .);
|
|
KEEP(*(.preinit_array*))
|
|
PROVIDE_HIDDEN(__preinit_array_end = .);
|
|
. = ALIGN(4);
|
|
} >FLASH
|
|
|
|
.init_array :
|
|
{
|
|
. = ALIGN(4);
|
|
PROVIDE_HIDDEN(__init_array_start = .);
|
|
KEEP(*(SORT(.init_array.*)))
|
|
KEEP(*(.init_array*))
|
|
PROVIDE_HIDDEN(__init_array_end = .);
|
|
. = ALIGN(4);
|
|
} >FLASH
|
|
|
|
.fini_array :
|
|
{
|
|
. = ALIGN(4);
|
|
PROVIDE_HIDDEN(__fini_array_start = .);
|
|
KEEP(*(SORT(.fini_array.*)))
|
|
KEEP(*(.fini_array*))
|
|
PROVIDE_HIDDEN(__fini_array_end = .);
|
|
. = ALIGN(4);
|
|
} >FLASH
|
|
|
|
/* _sidata: 초기화 데이터(.data)의 "원본" 위치(플래시). startup 이
|
|
* _sdata.._edata 로 복사한다. */
|
|
_sidata = LOADADDR(.data);
|
|
|
|
/* 4) 초기화된 데이터 (.data) — 실행 주소는 RAM, 로드 주소는 FLASH. */
|
|
.data :
|
|
{
|
|
. = ALIGN(4);
|
|
_sdata = .; /* .data 시작 (RAM) — startup 이 참조 */
|
|
*(.data)
|
|
*(.data*)
|
|
*(.RamFunc) /* RAM 에서 실행해야 하는 함수(예: 플래시 프로그래밍) */
|
|
*(.RamFunc*)
|
|
. = ALIGN(4);
|
|
_edata = .; /* .data 끝 (RAM) */
|
|
} >RAM AT> FLASH
|
|
|
|
/* 5) 초기화되지 않은 데이터 (.bss) — 0 으로 초기화(startup). */
|
|
.bss :
|
|
{
|
|
. = ALIGN(4);
|
|
_sbss = .; /* .bss 시작 — startup 이 참조 */
|
|
__bss_start__ = _sbss;
|
|
*(.bss)
|
|
*(.bss*)
|
|
*(COMMON)
|
|
. = ALIGN(4);
|
|
_ebss = .; /* .bss 끝 */
|
|
__bss_end__ = _ebss;
|
|
} >RAM
|
|
|
|
/* 6) 힙/스택 가드 — 최소 크기 확보(부족 시 링크 에러). */
|
|
._user_heap_stack :
|
|
{
|
|
. = ALIGN(8);
|
|
PROVIDE(end = .); /* newlib _sbrk 의 힙 시작(end / _end) */
|
|
PROVIDE(_end = .);
|
|
. = . + _Min_Heap_Size;
|
|
. = . + _Min_Stack_Size;
|
|
. = ALIGN(8);
|
|
} >RAM
|
|
|
|
/* 7) CCMRAM(.ccmram) — 코어 전용 64K. 비-DMA 데이터/스택 전용.
|
|
* 배치 예: __attribute__((section(".ccmram"))) static uint8_t ucHeap[...];
|
|
* 초기화 필요한 .ccmram 데이터를 쓰려면 .data 처럼 별도 복사 루프가 필요하나,
|
|
* 기본은 무초기화(NOLOAD) 영역으로 둔다(런타임에 명시 초기화 권장). */
|
|
.ccmram (NOLOAD) :
|
|
{
|
|
. = ALIGN(4);
|
|
_sccmram = .;
|
|
*(.ccmram)
|
|
*(.ccmram*)
|
|
. = ALIGN(4);
|
|
_eccmram = .;
|
|
} >CCMRAM
|
|
|
|
/* 디버그/주석 섹션 제거(산출물 슬림화). */
|
|
/DISCARD/ :
|
|
{
|
|
*(.ARM.attributes)
|
|
}
|
|
}
|