Last active 1 month ago

get_macbook_ramcfg Raw
1#!/usr/bin/env python3
2# =============================================================================
3# get_macbook_ramcfg
4# =============================================================================
5#
6# Decode Apple MacBook RAM configuration (RAMCFG) from Intel chipset GPIO
7# registers using output from `inteltool -g`.
8#
9# This script maps Apple’s undocumented GPIO-based RAM configuration
10# encoding to concrete memory vendor, size, and speed identifiers for
11# specific MacBook models.
12#
13# USAGE
14# sudo inteltool -g | get_macbook_ramcfg -m <MODEL>
15#
16# SUPPORTED MODELS
17# mbp101 - MacBook Pro 10,1
18# mba52 - MacBook Air 5,2
19# mba42 - MacBook Air 4,2
20#
21# NOTES
22# - Reads GPIO68–GPIO71 from the GPIO_LVL3 register
23# - Reverses bit order to match Apple’s wiring
24# - Uses RAMCFG value as an index into model-specific lookup tables
25#
26# CREDITS
27# Original implementation by ch1p (https://ch1p.io/)
28#
29# LICENSE
30# BSD-2-Clause
31#
32# EXTENSIONS & MAINTENANCE
33# Extended and maintained by Kris Yotam
34#
35# =============================================================================
36
37#!/usr/bin/env python3
38import sys
39import argparse
40
41
42ramconfigs = {
43 'mba42': (
44 '2b_hynix',
45 None,
46 '4g_hynix',
47 None,
48 '2g_samsung',
49 None,
50 '4g_samsung',
51 None,
52 '2g_micron',
53 None,
54 None,
55 None,
56 None,
57 None,
58 '4g_elpida',
59 ),
60 'mba52': (
61 '4g_hynix',
62 '4g_micron',
63 '8g_hynix',
64 None,
65 '4g_samsung',
66 None,
67 '8g_samsung',
68 None,
69 None,
70 None,
71 None,
72 None,
73 '4g_elpida',
74 None,
75 '8g_elpida',
76 ),
77 'mbp101': (
78 '4g_hynix_1600s',
79 '1g_samsung_1600',
80 '4g_samsung_1600s',
81 '1g_hynix_1600',
82 '4g_elpida_1600s',
83 '2g_samsung_1600',
84 '2g_samsung_1333',
85 '2g_hynix_1600',
86 '4g_samsung_1600',
87 '4g_hynix_1600',
88 '2g_elpida_1600s',
89 '2g_elpida_1600',
90 '4g_elpida_1600',
91 '2g_samsung_1600s',
92 '2g_hynix_1600s'
93 )
94}
95
96
97def main():
98 parser = argparse.ArgumentParser()
99 parser.add_argument('-m', '--model',
100 choices=list(ramconfigs.keys()),
101 help='MacBook model',
102 required=True)
103
104 args = parser.parse_args()
105
106 configs = ramconfigs[args.model]
107
108 reg = None
109 for line in sys.stdin:
110 line = line.strip()
111 if not line.endswith('(GPIO_LVL3)'):
112 continue
113
114 reg = int(line.split(' ')[1], 16)
115 break
116
117 if reg is None:
118 raise Exceptions("failed to parse gpio registers")
119
120 # GPIO68..GPIO71
121 ramcfg = (reg >> 4) & 0xf
122
123 # reverse bit order
124 ramcfg = int('{:04b}'.format(ramcfg)[::-1], 2)
125
126 if ramcfg >= len(configs) or configs[ramcfg] is None:
127 print("unsupported memory configuration %d" % ramcfg)
128 else:
129 print("%s (RAMCFG=%01x)" % (configs[ramcfg], ramcfg))
130
131
132if __name__ == '__main__':
133 main()
134