From 79d5903b6c5fff57712f02bc6fee888fcde414ce Mon Sep 17 00:00:00 2001
From: Wilba <Jason.S.Williams@gmail.com>
Date: Tue, 18 Feb 2020 12:54:13 +1100
Subject: [PATCH] dynamic keymap sanity check (#8181)

---
 quantum/dynamic_keymap.c | 24 ++++++++++++++++++++----
 1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/quantum/dynamic_keymap.c b/quantum/dynamic_keymap.c
index 0d8ea56b74..f4120b1184 100644
--- a/quantum/dynamic_keymap.c
+++ b/quantum/dynamic_keymap.c
@@ -30,6 +30,14 @@
 #    define DYNAMIC_KEYMAP_MACRO_COUNT 16
 #endif
 
+// This is the default EEPROM max address to use for dynamic keymaps.
+// The default is the ATmega32u4 EEPROM max address.
+// Explicitly override it if the keyboard uses a microcontroller with 
+// more EEPROM *and* it makes sense to increase it.
+#ifndef DYNAMIC_KEYMAP_EEPROM_MAX_ADDR
+#    define DYNAMIC_KEYMAP_EEPROM_MAX_ADDR 1023
+#endif
+
 // If DYNAMIC_KEYMAP_EEPROM_ADDR not explicitly defined in config.h,
 // default it start after VIA_EEPROM_CUSTOM_ADDR+VIA_EEPROM_CUSTOM_SIZE
 #ifndef DYNAMIC_KEYMAP_EEPROM_ADDR
@@ -45,11 +53,19 @@
 #    define DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR (DYNAMIC_KEYMAP_EEPROM_ADDR + (DYNAMIC_KEYMAP_LAYER_COUNT * MATRIX_ROWS * MATRIX_COLS * 2))
 #endif
 
-// Dynamic macro uses up all remaining memory
-// Assumes 1K EEPROM on ATMega32U4
-// Override for anything different
+// Sanity check that dynamic keymaps fit in available EEPROM
+// If there's not 100 bytes available for macros, then something is wrong.
+// The keyboard should override DYNAMIC_KEYMAP_LAYER_COUNT to reduce it,
+// or DYNAMIC_KEYMAP_EEPROM_MAX_ADDR to increase it, *only if* the microcontroller has
+// more than the default.
+#if DYNAMIC_KEYMAP_EEPROM_MAX_ADDR - DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR < 100
+#    error Dynamic keymaps are configured to use more EEPROM than is available.
+#endif
+
+// Dynamic macros are stored after the keymaps and use what is available
+// up to and including DYNAMIC_KEYMAP_EEPROM_MAX_ADDR.
 #ifndef DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE
-#    define DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE (1024 - DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR)
+#    define DYNAMIC_KEYMAP_MACRO_EEPROM_SIZE (DYNAMIC_KEYMAP_EEPROM_MAX_ADDR - DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR + 1)
 #endif
 
 uint8_t dynamic_keymap_get_layer_count(void) { return DYNAMIC_KEYMAP_LAYER_COUNT; }