From 5c4b53a1437adde49871752d8015bfc042b97c20 Mon Sep 17 00:00:00 2001
From: Drashna Jaelre <drashna@drashna.net>
Date: Mon, 8 May 2023 10:56:03 -0700
Subject: [PATCH] [Bug] Realign and size check EECONFIG structures (#20541)

Co-authored-by: Nick Brassel <nick@tzarc.org>
---
 docs/feature_led_matrix.md            |  8 +-------
 docs/feature_rgb_matrix.md            |  8 +-------
 quantum/audio/audio.h                 |  2 ++
 quantum/backlight/backlight.h         |  2 ++
 quantum/eeconfig.c                    | 17 +++++++----------
 quantum/eeconfig.h                    | 17 +++++++----------
 quantum/haptic.h                      |  6 ++++--
 quantum/keycode_config.h              |  6 ++++++
 quantum/led_matrix/led_matrix_types.h |  5 +++--
 quantum/rgb_matrix/rgb_matrix_types.h |  6 ++++--
 quantum/rgblight/rgblight.c           | 21 +++++++++++----------
 quantum/rgblight/rgblight.h           | 15 ++++++++-------
 quantum/unicode/unicode.h             |  4 +++-
 13 files changed, 59 insertions(+), 58 deletions(-)

diff --git a/docs/feature_led_matrix.md b/docs/feature_led_matrix.md
index 1cde9b66e1..bc86099f1f 100644
--- a/docs/feature_led_matrix.md
+++ b/docs/feature_led_matrix.md
@@ -378,13 +378,7 @@ For inspiration and examples, check out the built-in effects under `quantum/led_
 
 ## EEPROM storage :id=eeprom-storage
 
-The EEPROM for it is currently shared with the RGB Matrix system (it's generally assumed only one feature would be used at a time), but could be configured to use its own 32bit address with:
-
-```c
-#define EECONFIG_LED_MATRIX (uint32_t *)28
-```
-
-Where `28` is an unused index from `eeconfig.h`.
+The EEPROM for it is currently shared with the RGB Matrix system (it's generally assumed only one feature would be used at a time).
 
 ### Direct Operation :id=direct-operation
 |Function                                    |Description  |
diff --git a/docs/feature_rgb_matrix.md b/docs/feature_rgb_matrix.md
index de36f95fb7..75f07b5e64 100644
--- a/docs/feature_rgb_matrix.md
+++ b/docs/feature_rgb_matrix.md
@@ -893,13 +893,7 @@ These are defined in [`color.h`](https://github.com/qmk/qmk_firmware/blob/master
 
 ## EEPROM storage :id=eeprom-storage
 
-The EEPROM for it is currently shared with the LED Matrix system (it's generally assumed only one feature would be used at a time), but could be configured to use its own 32bit address with:
-
-```c
-#define EECONFIG_RGB_MATRIX (uint32_t *)28
-```
-
-Where `28` is an unused index from `eeconfig.h`.
+The EEPROM for it is currently shared with the LED Matrix system (it's generally assumed only one feature would be used at a time).
 
 ## Functions :id=functions
 
diff --git a/quantum/audio/audio.h b/quantum/audio/audio.h
index 497f3dafd0..75016a1100 100644
--- a/quantum/audio/audio.h
+++ b/quantum/audio/audio.h
@@ -43,6 +43,8 @@ typedef union {
     };
 } audio_config_t;
 
+_Static_assert(sizeof(audio_config_t) == sizeof(uint8_t), "Audio EECONFIG out of spec.");
+
 /*
  * a 'musical note' is represented by pitch and duration; a 'musical tone' adds intensity and timbre
  * https://en.wikipedia.org/wiki/Musical_tone
diff --git a/quantum/backlight/backlight.h b/quantum/backlight/backlight.h
index ff9c8de420..85812bff3a 100644
--- a/quantum/backlight/backlight.h
+++ b/quantum/backlight/backlight.h
@@ -44,6 +44,8 @@ typedef union {
     };
 } backlight_config_t;
 
+_Static_assert(sizeof(backlight_config_t) == sizeof(uint8_t), "Backlight EECONFIG out of spec.");
+
 void    backlight_init(void);
 void    backlight_toggle(void);
 void    backlight_enable(void);
diff --git a/quantum/eeconfig.c b/quantum/eeconfig.c
index 21bcce2654..84de025f0e 100644
--- a/quantum/eeconfig.c
+++ b/quantum/eeconfig.c
@@ -46,6 +46,7 @@ void eeconfig_init_quantum(void) {
 #if defined(EEPROM_DRIVER)
     eeprom_driver_erase();
 #endif
+
     eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER);
     eeprom_update_byte(EECONFIG_DEBUG, 0);
     eeprom_update_byte(EECONFIG_DEFAULT_LAYER, 0);
@@ -55,19 +56,15 @@ void eeconfig_init_quantum(void) {
     eeprom_update_byte(EECONFIG_BACKLIGHT, 0);
     eeprom_update_byte(EECONFIG_AUDIO, 0xFF); // On by default
     eeprom_update_dword(EECONFIG_RGBLIGHT, 0);
-    eeprom_update_byte(EECONFIG_STENOMODE, 0);
-    eeprom_update_dword(EECONFIG_HAPTIC, 0);
+    eeprom_update_byte(EECONFIG_RGBLIGHT_EXTENDED, 0);
     eeprom_update_byte(EECONFIG_VELOCIKEY, 0);
-    eeprom_update_dword(EECONFIG_RGB_MATRIX, 0);
-    eeprom_update_word(EECONFIG_RGB_MATRIX_EXTENDED, 0);
-
+    eeprom_update_byte(EECONFIG_UNICODEMODE, 0);
+    eeprom_update_byte(EECONFIG_STENOMODE, 0);
+    uint64_t dummy = 0;
+    eeprom_update_block(&dummy, EECONFIG_RGB_MATRIX, sizeof(uint64_t));
+    eeprom_update_dword(EECONFIG_HAPTIC, 0);
 #if defined(HAPTIC_ENABLE)
     haptic_reset();
-#else
-    // this is used in case haptic is disabled, but we still want sane defaults
-    // in the haptic configuration eeprom. All zero will trigger a haptic_reset
-    // when a haptic-enabled firmware is loaded onto the keyboard.
-    eeprom_update_dword(EECONFIG_HAPTIC, 0);
 #endif
 
 #if (EECONFIG_KB_DATA_SIZE) > 0
diff --git a/quantum/eeconfig.h b/quantum/eeconfig.h
index ee8e9add8b..85e80226b6 100644
--- a/quantum/eeconfig.h
+++ b/quantum/eeconfig.h
@@ -21,7 +21,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include <stdbool.h>
 
 #ifndef EECONFIG_MAGIC_NUMBER
-#    define EECONFIG_MAGIC_NUMBER (uint16_t)0xFEE7 // When changing, decrement this value to avoid future re-init issues
+#    define EECONFIG_MAGIC_NUMBER (uint16_t)0xFEE6 // When changing, decrement this value to avoid future re-init issues
 #endif
 #define EECONFIG_MAGIC_NUMBER_OFF (uint16_t)0xFFFF
 
@@ -40,18 +40,15 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #define EECONFIG_KEYBOARD (uint32_t *)15
 #define EECONFIG_USER (uint32_t *)19
 #define EECONFIG_VELOCIKEY (uint8_t *)23
-
-#define EECONFIG_HAPTIC (uint32_t *)24
-
 // Mutually exclusive
-#define EECONFIG_LED_MATRIX (uint32_t *)28
-#define EECONFIG_RGB_MATRIX (uint32_t *)28
-// Speed & Flags
-#define EECONFIG_LED_MATRIX_EXTENDED (uint16_t *)32
-#define EECONFIG_RGB_MATRIX_EXTENDED (uint16_t *)32
+#define EECONFIG_LED_MATRIX (uint32_t *)24
+#define EECONFIG_RGB_MATRIX (uint64_t *)24
+
+#define EECONFIG_HAPTIC (uint32_t *)32
+#define EECONFIG_RGBLIGHT_EXTENDED (uint8_t *)36
 
 // Size of EEPROM being used for core data storage
-#define EECONFIG_BASE_SIZE 34
+#define EECONFIG_BASE_SIZE 37
 
 // Size of EEPROM dedicated to keyboard- and user-specific data
 #ifndef EECONFIG_KB_DATA_SIZE
diff --git a/quantum/haptic.h b/quantum/haptic.h
index 7d70a01333..71d95cc61b 100644
--- a/quantum/haptic.h
+++ b/quantum/haptic.h
@@ -31,16 +31,18 @@ typedef union {
     uint32_t raw;
     struct {
         bool    enable : 1;
-        uint8_t feedback : 2;
         uint8_t mode : 7;
         bool    buzz : 1;
         uint8_t dwell : 7;
-        bool    cont : 1;
         uint8_t amplitude : 8;
+        uint8_t feedback : 2;
+        bool    cont : 1;
         uint8_t reserved : 5;
     };
 } haptic_config_t;
 
+_Static_assert(sizeof(haptic_config_t) == sizeof(uint32_t), "Haptic EECONFIG out of spec.");
+
 typedef enum HAPTIC_FEEDBACK {
     KEY_PRESS,
     KEY_PRESS_RELEASE,
diff --git a/quantum/keycode_config.h b/quantum/keycode_config.h
index eef048d95c..d1352c302e 100644
--- a/quantum/keycode_config.h
+++ b/quantum/keycode_config.h
@@ -16,6 +16,10 @@
 
 #pragma once
 
+#ifdef __cplusplus
+#    define _Static_assert static_assert
+#endif
+
 #include "eeconfig.h"
 #include "keycode.h"
 #include "action_code.h"
@@ -43,4 +47,6 @@ typedef union {
     };
 } keymap_config_t;
 
+_Static_assert(sizeof(keymap_config_t) == sizeof(uint16_t), "Keycode (magic) EECONFIG out of spec.");
+
 extern keymap_config_t keymap_config;
diff --git a/quantum/led_matrix/led_matrix_types.h b/quantum/led_matrix/led_matrix_types.h
index 6d79a3592d..6709a558bb 100644
--- a/quantum/led_matrix/led_matrix_types.h
+++ b/quantum/led_matrix/led_matrix_types.h
@@ -85,13 +85,14 @@ typedef union {
     struct PACKED {
         uint8_t     enable : 2;
         uint8_t     mode : 6;
-        uint16_t    reserved;
         uint8_t     val;
-        uint8_t     speed; // EECONFIG needs to be increased to support this
+        uint8_t     speed;
         led_flags_t flags;
     };
 } led_eeconfig_t;
 
+_Static_assert(sizeof(led_eeconfig_t) == sizeof(uint32_t), "LED Matrix EECONFIG out of spec.");
+
 #if defined(_MSC_VER)
 #    pragma pack(pop)
 #endif
diff --git a/quantum/rgb_matrix/rgb_matrix_types.h b/quantum/rgb_matrix/rgb_matrix_types.h
index eea603c41c..53ff7321b8 100644
--- a/quantum/rgb_matrix/rgb_matrix_types.h
+++ b/quantum/rgb_matrix/rgb_matrix_types.h
@@ -83,16 +83,18 @@ typedef struct PACKED {
 } led_config_t;
 
 typedef union {
-    uint32_t raw;
+    uint64_t raw;
     struct PACKED {
         uint8_t     enable : 2;
         uint8_t     mode : 6;
         HSV         hsv;
-        uint8_t     speed; // EECONFIG needs to be increased to support this
+        uint8_t     speed;
         led_flags_t flags;
     };
 } rgb_config_t;
 
+_Static_assert(sizeof(rgb_config_t) == sizeof(uint64_t), "RGB Matrix EECONFIG out of spec.");
+
 #if defined(_MSC_VER)
 #    pragma pack(pop)
 #endif
diff --git a/quantum/rgblight/rgblight.c b/quantum/rgblight/rgblight.c
index 02188df95b..ea28801a40 100644
--- a/quantum/rgblight/rgblight.c
+++ b/quantum/rgblight/rgblight.c
@@ -177,18 +177,19 @@ void rgblight_check_config(void) {
     }
 }
 
-uint32_t eeconfig_read_rgblight(void) {
+uint64_t eeconfig_read_rgblight(void) {
 #ifdef EEPROM_ENABLE
-    return eeprom_read_dword(EECONFIG_RGBLIGHT);
+    return (uint64_t)((eeprom_read_dword(EECONFIG_RGBLIGHT)) | ((uint64_t)eeprom_read_byte(EECONFIG_RGBLIGHT_EXTENDED) << 32));
 #else
     return 0;
 #endif
 }
 
-void eeconfig_update_rgblight(uint32_t val) {
+void eeconfig_update_rgblight(uint64_t val) {
 #ifdef EEPROM_ENABLE
     rgblight_check_config();
-    eeprom_update_dword(EECONFIG_RGBLIGHT, val);
+    eeprom_update_dword(EECONFIG_RGBLIGHT, val & 0xFFFFFFFF);
+    eeprom_update_byte(EECONFIG_RGBLIGHT_EXTENDED, (val >> 32) & 0xFF);
 #endif
 }
 
@@ -263,13 +264,13 @@ void rgblight_reload_from_eeprom(void) {
     }
 }
 
-uint32_t rgblight_read_dword(void) {
+uint64_t rgblight_read_qword(void) {
     return rgblight_config.raw;
 }
 
-void rgblight_update_dword(uint32_t dword) {
+void rgblight_update_qword(uint64_t qword) {
     RGBLIGHT_SPLIT_SET_CHANGE_MODEHSVS;
-    rgblight_config.raw = dword;
+    rgblight_config.raw = qword;
     if (rgblight_config.enable)
         rgblight_mode_noeeprom(rgblight_config.mode);
     else {
@@ -489,7 +490,7 @@ void rgblight_increase_speed_helper(bool write_to_eeprom) {
     if (rgblight_config.speed < 3) rgblight_config.speed++;
     // RGBLIGHT_SPLIT_SET_CHANGE_HSVS; // NEED?
     if (write_to_eeprom) {
-        eeconfig_update_rgblight(rgblight_config.raw); // EECONFIG needs to be increased to support this
+        eeconfig_update_rgblight(rgblight_config.raw);
     }
 }
 void rgblight_increase_speed(void) {
@@ -503,7 +504,7 @@ void rgblight_decrease_speed_helper(bool write_to_eeprom) {
     if (rgblight_config.speed > 0) rgblight_config.speed--;
     // RGBLIGHT_SPLIT_SET_CHANGE_HSVS; // NEED??
     if (write_to_eeprom) {
-        eeconfig_update_rgblight(rgblight_config.raw); // EECONFIG needs to be increased to support this
+        eeconfig_update_rgblight(rgblight_config.raw);
     }
 }
 void rgblight_decrease_speed(void) {
@@ -612,7 +613,7 @@ uint8_t rgblight_get_speed(void) {
 void rgblight_set_speed_eeprom_helper(uint8_t speed, bool write_to_eeprom) {
     rgblight_config.speed = speed;
     if (write_to_eeprom) {
-        eeconfig_update_rgblight(rgblight_config.raw); // EECONFIG needs to be increased to support this
+        eeconfig_update_rgblight(rgblight_config.raw);
         dprintf("rgblight set speed [EEPROM]: %u\n", rgblight_config.speed);
     } else {
         dprintf("rgblight set speed [NOEEPROM]: %u\n", rgblight_config.speed);
diff --git a/quantum/rgblight/rgblight.h b/quantum/rgblight/rgblight.h
index 2e85541313..001058f962 100644
--- a/quantum/rgblight/rgblight.h
+++ b/quantum/rgblight/rgblight.h
@@ -244,19 +244,20 @@ extern const uint16_t RGBLED_RGBTEST_INTERVALS[1] PROGMEM;
 extern const uint8_t  RGBLED_TWINKLE_INTERVALS[3] PROGMEM;
 extern bool           is_rgblight_initialized;
 
-// Should stay in sycn with rgb matrix config as we reuse eeprom storage for both (for now)
 typedef union {
-    uint32_t raw;
+    uint64_t raw;
     struct {
         bool    enable : 1;
         uint8_t mode : 7;
         uint8_t hue : 8;
         uint8_t sat : 8;
         uint8_t val : 8;
-        uint8_t speed : 8; // EECONFIG needs to be increased to support this
+        uint8_t speed : 8;
     };
 } rgblight_config_t;
 
+_Static_assert(sizeof(rgblight_config_t) == sizeof(uint64_t), "RGB Light EECONFIG out of spec.");
+
 typedef struct _rgblight_status_t {
     uint8_t base_mode;
     bool    timer_enabled;
@@ -367,10 +368,10 @@ HSV     rgblight_get_hsv(void);
 void     rgblight_init(void);
 void     rgblight_suspend(void);
 void     rgblight_wakeup(void);
-uint32_t rgblight_read_dword(void);
-void     rgblight_update_dword(uint32_t dword);
-uint32_t eeconfig_read_rgblight(void);
-void     eeconfig_update_rgblight(uint32_t val);
+uint64_t rgblight_read_qword(void);
+void     rgblight_update_qword(uint64_t qword);
+uint64_t eeconfig_read_rgblight(void);
+void     eeconfig_update_rgblight(uint64_t val);
 void     eeconfig_update_rgblight_current(void);
 void     eeconfig_update_rgblight_default(void);
 void     eeconfig_debug_rgblight(void);
diff --git a/quantum/unicode/unicode.h b/quantum/unicode/unicode.h
index 6f1e35d554..06505d87c0 100644
--- a/quantum/unicode/unicode.h
+++ b/quantum/unicode/unicode.h
@@ -21,12 +21,14 @@
 #include "quantum.h"
 
 typedef union {
-    uint32_t raw;
+    uint8_t raw;
     struct {
         uint8_t input_mode : 8;
     };
 } unicode_config_t;
 
+_Static_assert(sizeof(unicode_config_t) == sizeof(uint8_t), "Unicode EECONFIG out of spec.");
+
 extern unicode_config_t unicode_config;
 
 enum unicode_input_modes {