POSA_LEAKSMS/firmware/ld/STM32F407VGTx_FLASH.ld
유창욱 90f121e14c chore: import codebase with security hardening
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 제외.
2026-06-20 09:37:40 +09:00

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)
}
}