/**
 * @file WSPN_Security.c
 * @brief 디버거 감지 및 RDP 상태 정확히 확인
 */

#include "WSPN_Security.h"
#include "flash.h"

// 디버거 감지 상태 변수
volatile uint8_t g_debugger_detected = 0;

/**
 * @brief RDP 상태 확인 함수 (개선된 버전)
 * @return 1: RDP 레벨 1 활성화됨, 0: RDP 레벨 0 (보호 없음)
 */
uint8_t WSPN_CheckRDPStatus(void) {
    // 옵션 바이트 주소에서 직접 RDP 값 읽기
    // STM32F446의 옵션 바이트는 0x1FFFC000 주소에 위치
    volatile uint8_t *rdp_addr = (uint8_t*)0x1FFFC000;
    uint8_t rdp_value = *rdp_addr;

    // RDP 레벨 0는 0xAA 값을 가짐, 그 외는 보호된 상태
    return (rdp_value == 0xAA) ? 0 : 1;
}

/**
 * @brief 디버거 감지 함수
 * @return 1: 디버거 감지됨, 0: 감지되지 않음
 */
uint8_t WSPN_SECURITY_IsDebuggerPresent(void) {
    // CoreDebug DHCSR 레지스터를 통한 디버그 상태 확인
    volatile uint32_t *dhcsr = (uint32_t*)0xE000EDF0;

    // C_DEBUGEN 비트(비트 0)가 설정되어 있으면 디버거가 연결됨
    return (*dhcsr & 1) ? 1 : 0;
}

/**
 * 메인 펌웨어 영역(섹터 1) 삭제 함수
 */
void WSPN_SECURITY_EraseMainFirmware(void) {
    HAL_FLASH_Unlock();
    HAL_StatusTypeDef status = Flash_Erase(FLASH_SECTOR_1);

    if (status == HAL_OK) {
        UART3_printf("Main FW (Sector 1) erased successfully!\r\n");
    } else {
        UART3_printf("Main FW erase failed!\r\n");
    }

    // 시스템 리셋
    NVIC_SystemReset();
}

void WSPN_SECURITY_RUN(void) {
    // 부팅 시 1회만 RDP 상태 확인 및 표시
    static uint8_t first_run = 1;
    if (first_run) {
        first_run = 0;

        // RDP 상태 확인 및 표시
        if (WSPN_CheckRDPStatus()) {
            UART3_printf("RDP protection is active. Firmware is protected from reading.\r\n");
        } else {
            UART3_printf("WARNING: RDP is not active! Firmware is not protected.\r\n");
        }
    }

    // 최초 프로그래밍인지 확인 (RAM_Data.VerMiner == 0이면 최초 프로그래밍)
    if (RAM_Data.VerMiner == 0) {
        // 최초 프로그래밍은 디버거 허용
        if (WSPN_SECURITY_IsDebuggerPresent()) {
            RAM_Data.VerMiner = 1;
            Save_Data_to_Flash();
        }
        return; // 최초 프로그래밍은 항상 허용
    }

    // 이미 프로그래밍된 상태 (VerMiner != 0)
    g_debugger_detected = WSPN_SECURITY_IsDebuggerPresent();
    if (g_debugger_detected) {
        UART3_printf("How dare you hack RoomFit!\r\n");

        // 디버거 감지 이력 저장
        RAM_Data.VerMajer = 9;
        Save_Data_to_Flash();
        Delay_msec(500);

        // 플래시 삭제 및 리셋
        WSPN_SECURITY_EraseMainFirmware();
    }

    // 해킹 시도 감지됐던 경우 메시지만 표시
    if (RAM_Data.VerMajer == 9) {
        static uint8_t message_count = 0;
        if (message_count < 5) {
            message_count++;
            UART3_printf("Hacking tried!!\r\n");
        }
    }
}

///**
// * @file WSPN_Security.c
// * @brief 확장된 디버거 감지 및 플래시 보호 기능 구현
// */
//
//#include "WSPN_Security.h"
//#include "flash.h"
//
//// 디버거 감지 상태 변수
//volatile uint8_t g_debugger_detected = 0;
//
///**
// * @brief 확장된 디버거 감지 함수 (CubeProgrammer 포함)
// * @return 1: 디버거 감지됨, 0: 감지되지 않음
// */
//uint8_t WSPN_SECURITY_IsDebuggerPresent(void) {
//    // 1. CoreDebug DHCSR 레지스터 확인
//    volatile uint32_t *dhcsr = (uint32_t*)0xE000EDF0;
//    if (*dhcsr & 1) {
//        return 1; // 디버거 감지됨
//    }
//
//    // 2. DBGMCU 레지스터 확인
//    volatile uint32_t *dbgmcu_cr = (uint32_t*)0xE0042004;
//    if (*dbgmcu_cr & 0x00000007) {
//        return 1; // 디버그 기능 활성화됨
//    }
//
//    // 3. 플래시 레지스터 확인 (CubeProgrammer는 이 레지스터에 접근)
//    volatile uint32_t *flash_cr = (uint32_t*)0x40023C10; // FLASH_CR 레지스터
//    if (*flash_cr & 0x00000200) { // STRT 비트 또는 PG 비트 확인
//        return 1; // 플래시 프로그래밍 진행 중
//    }
//
//    // 4. SWD 핀 상태 확인 (SWD 인터페이스를 통한 접근 감지)
//    // 참고: 이 부분은 하드웨어 구성에 따라 달라질 수 있음
//    RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; // GPIOA 클럭 활성화
//
//    // SWDIO 핀 상태 확인 (일반적으로 PA13)
//    GPIOA->MODER &= ~GPIO_MODER_MODER13; // 입력 모드로 설정
//    if ((GPIOA->IDR & GPIO_PIN_13) == 0) {
//        // SWDIO가 LOW 상태일 때 - 디버거가 연결되어 있을 가능성
//        return 1;
//    }
//
//    // SWCLK 핀 상태 확인 (일반적으로 PA14)
//    GPIOA->MODER &= ~GPIO_MODER_MODER14; // 입력 모드로 설정
//    if ((GPIOA->IDR & GPIO_PIN_14) == 0) {
//        // SWCLK가 LOW 상태일 때 - 디버거가 연결되어 있을 가능성
//        return 1;
//    }
//
//    // 5. 실행 시간 체크 (디버거 연결 시 실행이 지연됨)
//    static uint32_t prev_time = 0;
//    static uint32_t abnormal_timing_count = 0;
//
//    uint32_t current_time = HAL_GetTick();
//    uint32_t elapsed = current_time - prev_time;
//    prev_time = current_time;
//
//    // 첫 호출이 아닌 경우만 시간 체크
//    if (prev_time > 0) {
//        if (elapsed > 1000) { // 비정상적으로 긴 간격 (1초 이상)
//            abnormal_timing_count++;
//            if (abnormal_timing_count > 3) {
//                return 1; // 여러 번 비정상적 간격이 감지되면 디버거로 판단
//            }
//        } else {
//            // 정상 간격에서는 카운터 감소
//            if (abnormal_timing_count > 0) {
//                abnormal_timing_count--;
//            }
//        }
//    }
//
//    return 0; // 디버거가 감지되지 않음
//}
//
///**
// * 메인 펌웨어 영역(섹터 1) 삭제 함수
// */
//void WSPN_SECURITY_EraseMainFirmware(void) {
//    HAL_FLASH_Unlock();
//    HAL_StatusTypeDef status = Flash_Erase(FLASH_SECTOR_1);
//
//    if (status == HAL_OK) {
//        UART3_printf("Main FW (Sector 1) erased successfully!\r\n");
//    } else {
//        UART3_printf("Main FW erase failed!\r\n");
//    }
//
//    // 시스템 리셋
//    NVIC_SystemReset();
//}
//
//// 전역 변수
//uint8_t message_count = 0;
//
//void WSPN_SECURITY_RUN(void) {
//    // 최초 프로그래밍 여부 확인 (RAM_Data.VerMiner == 0이면 최초 프로그래밍)
//    if (RAM_Data.VerMiner == 0) {
//        // 최초 프로그래밍 중 디버거 감지 시 허용
//        if (WSPN_SECURITY_IsDebuggerPresent()) {
//            // 프로그래밍 완료 마킹
//            RAM_Data.VerMiner = 1;
//            Save_Data_to_Flash();
//            return; // 디버거 감지했지만 최초 프로그래밍이므로 허용
//        }
//    }
//    // 이미 프로그래밍된 상태 (VerMiner != 0)
//    else {
//        g_debugger_detected = WSPN_SECURITY_IsDebuggerPresent();
//        if (g_debugger_detected) {
//            UART3_printf("How dare you hack RoomFit!\r\n");
//            Delay_msec(500);
//            // 디버거 감지 이력 저장
//            RAM_Data.VerMajer = 9;
//            Save_Data_to_Flash();
//            Delay_msec(500);
//            // 플래시 삭제 및 리셋
//            WSPN_SECURITY_EraseMainFirmware();
//        }
//    }
//
//    // 해킹 시도 감지됐던 경우 메시지만 표시
//    if (RAM_Data.VerMajer == 9) {
//        static uint8_t message_count = 0;
//        if (message_count < 5) {
//            message_count++;
//            UART3_printf("Hacking tried!!\r\n");
//        }
//    }
//}
