├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── intelmetool.c ├── intelmetool.h ├── me.c ├── me.h ├── me_status.c ├── mmap.c └── mmap.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | intelmetool 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | intelmetool 2 | 3 | Copyright (C) 2013-2018 Damien Zammit 4 | 5 | NB: Since 3 of the source files seem to be licensed GPL-2.0-only, 6 | This project is currently covered under GPL-2.0-only. 7 | 8 | This program is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU General Public License as 10 | published by the Free Software Foundation; version 2 of the License. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC= gcc 2 | CFLAGS= -Wall -O0 -g 3 | LIBS= -lpci 4 | 5 | INCLUDES= -I. 6 | 7 | SRCS= intelmetool.c \ 8 | me_status.c \ 9 | me.c \ 10 | mmap.c 11 | 12 | OBJS = $(SRCS:.c=.o) 13 | 14 | TARGET= intelmetool 15 | 16 | 17 | .PHONY: depend clean 18 | 19 | all: $(TARGET) 20 | 21 | $(TARGET): $(OBJS) 22 | $(CC) $(CFLAGS) $(INCLUDES) -o $(TARGET) $(OBJS) $(LIBS) 23 | 24 | .c.o: 25 | $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ 26 | 27 | clean: 28 | rm $(TARGET) *.o 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | intelmetool 2 | =========== 3 | 4 | Compiling: 5 | ========== 6 | 7 | You need libpci-dev 8 | 9 | Running: 10 | ======== 11 | 12 | You need to `sudo rmmod mei_me` and `sudo rmmod mei` before using this tool. 13 | Also pass `iomem=relaxed` to kernel commandline if you are on kernel 4.4+ 14 | 15 | Interesting to compare output with and without partially removing ME with 16 | `me_cleaner`. 17 | (NB: Always back up your BIOS when fiddling with ME firmware) 18 | 19 | ``` 20 | make 21 | sudo ./intelmetool 22 | ``` 23 | -------------------------------------------------------------------------------- /intelmetool.c: -------------------------------------------------------------------------------- 1 | /* intelmetool Dump interesting things about Management Engine even if hidden 2 | * Copyright (C) 2014 Damien Zammit 3 | * 4 | * This program is free software; you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation; either version 2 of the License, 7 | * or (at your option), any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include "me.h" 25 | #include "mmap.h" 26 | #include "intelmetool.h" 27 | 28 | extern int fd_mem; 29 | #define FD2 0x3428 30 | 31 | void dumpmem(uint8_t *phys, uint32_t size) 32 | { 33 | uint32_t i; 34 | printf("Dumping cloned ME memory:\n"); 35 | for (i = 0; i < size; i++) { 36 | printf("%02X",*((uint8_t *) (phys + i))); 37 | } 38 | printf("\n"); 39 | } 40 | 41 | void zeroit(uint8_t *phys, uint32_t size) 42 | { 43 | uint32_t i; 44 | for (i = 0; i < size; i++) { 45 | *((uint8_t *) (phys + i)) = 0x00; 46 | } 47 | } 48 | 49 | void dumpmemfile(uint8_t *phys, uint32_t size) 50 | { 51 | FILE *fp = fopen("medump.bin", "w"); 52 | uint32_t i; 53 | for (i = 0; i < size; i++) { 54 | fprintf(fp, "%c", *((uint8_t *) (phys + i))); 55 | } 56 | fclose(fp); 57 | } 58 | 59 | int main(void) 60 | { 61 | struct pci_access *pacc; 62 | struct pci_dev *dev; 63 | struct pci_dev *sb; 64 | uint32_t stat, stat2; 65 | char namebuf[1024], *name; 66 | int size = 0x4000; 67 | if (iopl(3)) { 68 | perror("iopl"); 69 | printf("You need to be root\n"); 70 | exit(1); 71 | } 72 | 73 | if ((fd_mem = open("/dev/mem", O_RDWR)) < 0) { 74 | perror("Can not open /dev/mem"); 75 | exit(1); 76 | } 77 | 78 | volatile uint8_t *rcba; 79 | uint32_t rcba_phys; 80 | uint32_t fd2; 81 | uint8_t me; 82 | 83 | pacc = pci_alloc(); 84 | pacc->method = PCI_ACCESS_I386_TYPE1; 85 | pci_init(pacc); 86 | pci_scan_bus(pacc); 87 | me = ME_FOUND_NOTHING; 88 | for (dev=pacc->devices; dev; dev=dev->next) { 89 | pci_fill_info(dev, PCI_FILL_IDENT | PCI_FILL_BASES | PCI_FILL_SIZES | PCI_FILL_CLASS); 90 | name = pci_lookup_name(pacc, namebuf, sizeof(namebuf), 91 | PCI_LOOKUP_DEVICE, dev->vendor_id, dev->device_id); 92 | if (dev->vendor_id == 0x8086) { 93 | if (PCI_DEV_NO_ME(dev->device_id)) { 94 | me = ME_NOT_PRESENT; 95 | break; 96 | } 97 | if (PCI_DEV_HAS_ME_DISABLE(dev->device_id)) { 98 | me = ME_PRESENT_CAN_DISABLE; 99 | break; 100 | } 101 | if (PCI_DEV_HAS_ME_DIFFICULT(dev->device_id)) { 102 | me = ME_PRESENT_CANNOT_DISABLE; 103 | break; 104 | } 105 | if (PCI_DEV_CAN_DISABLE_ME_IF_PRESENT(dev->device_id)) { 106 | me = ME_CAN_DISABLE_IF_PRESENT; 107 | break; 108 | } 109 | if (PCI_DEV_ME_NOT_SURE(dev->device_id)) { 110 | me = ME_FOUND_SOMETHING_NOT_SURE; 111 | break; 112 | } 113 | } 114 | } 115 | 116 | switch (me) { 117 | case ME_FOUND_NOTHING: 118 | printf("Hardware unsupported by intelmetool, exiting\n"); 119 | pci_cleanup(pacc); 120 | exit(ME_FOUND_NOTHING); 121 | break; 122 | case ME_FOUND_SOMETHING_NOT_SURE: 123 | printf("Found `%s`. Not sure whether you have ME hardware, exiting\n", name); 124 | pci_cleanup(pacc); 125 | exit(ME_FOUND_SOMETHING_NOT_SURE); 126 | break; 127 | case ME_NOT_PRESENT: 128 | printf("ME is not present on your board because we found a `%s`, you are safe, exiting\n", name); 129 | pci_cleanup(pacc); 130 | exit(ME_NOT_PRESENT); 131 | break; 132 | case ME_CAN_DISABLE_IF_PRESENT: 133 | printf("Not sure if ME hardware is present because you have a `%s`, but it is possible to disable it if you do, continuing...\n", name); 134 | break; 135 | case ME_PRESENT_CANNOT_DISABLE: 136 | printf("Bad news, you have a `%s` so you have ME hardware on board and it is very difficult to remove, continuing...\n", name); 137 | break; 138 | case ME_PRESENT_CAN_DISABLE: 139 | printf("Good news, you have a `%s` so ME is present but can be disabled, continuing...\n", name); 140 | break; 141 | default: 142 | printf("Something horrible happened, exiting\n"); 143 | pci_cleanup(pacc); 144 | exit(1); 145 | break; 146 | } 147 | 148 | 149 | pacc = pci_alloc(); 150 | pacc->method = PCI_ACCESS_I386_TYPE1; 151 | pci_init(pacc); 152 | pci_scan_bus(pacc); 153 | sb = pci_get_dev(pacc, 0, 0, 0x1f, 0); 154 | if (!sb) { 155 | printf("Uh oh, southbridge not on BDF(0:31:0), please report this error, exiting.\n"); 156 | pci_cleanup(pacc); 157 | exit(1); 158 | } 159 | pci_fill_info(sb, PCI_FILL_IDENT | PCI_FILL_BASES | PCI_FILL_SIZES | PCI_FILL_CLASS); 160 | 161 | /* Enable MEI */ 162 | rcba_phys = pci_read_long(sb, 0xf0) & 0xfffffffe; 163 | rcba = map_physical(rcba_phys, size); 164 | printf("RCBA at 0x%08" PRIx32 "\n", (uint32_t)rcba_phys); 165 | fd2 = *(uint32_t *)(rcba + FD2); 166 | *(uint32_t *)(rcba + FD2) = fd2 & ~0x2; 167 | if (fd2 & 0x2) { 168 | printf("MEI was hidden on PCI, now unlocked\n"); 169 | } else { 170 | printf("MEI not hidden on PCI, checking if visible\n"); 171 | } 172 | 173 | pci_cleanup(pacc); 174 | 175 | pacc = pci_alloc(); 176 | pacc->method = PCI_ACCESS_I386_TYPE1; 177 | pci_init(pacc); 178 | pci_scan_bus(pacc); 179 | me = 0; 180 | for (dev=pacc->devices; dev; dev=dev->next) { 181 | pci_fill_info(dev, PCI_FILL_IDENT | PCI_FILL_BASES | PCI_FILL_SIZES | PCI_FILL_CLASS); 182 | name = pci_lookup_name(pacc, namebuf, sizeof(namebuf), 183 | PCI_LOOKUP_DEVICE, dev->vendor_id, dev->device_id); 184 | if (dev->vendor_id == 0x8086) { 185 | switch (dev->device_id) { 186 | case 0x1C3A: /* Cougar Point */ 187 | case 0x1CBA: /* Panther Point */ 188 | case 0x1D3A: /* C600/X79 Patsburg */ 189 | case 0x1DBA: /* Panther Point */ 190 | case 0x1E3A: /* Panther Point */ 191 | case 0x2364: /* Cave Creek */ 192 | case 0x28B4: /* Bearlake */ 193 | case 0x28C4: /* Bearlake */ 194 | case 0x28D4: /* Bearlake */ 195 | case 0x28E4: /* Bearlake */ 196 | case 0x28F4: /* Bearlake */ 197 | case 0x2974: /* 82946GZ/GL */ 198 | case 0x2984: /* 82G35 Express */ 199 | case 0x2994: /* 82Q963/Q965 */ 200 | case 0x29A4: /* 82P965/G965 */ 201 | case 0x29B4: /* 82Q35 Express */ 202 | case 0x29C4: /* 82G33/G31/P35/P31 Express */ 203 | case 0x29D4: /* 82Q33 Express */ 204 | case 0x29E4: /* 82X38/X48 Express */ 205 | case 0x29F4: /* 3200/3210 Server */ 206 | case 0x2A04: /* Mobile PM965/GM965 */ 207 | case 0x2A14: /* Mobile GME965/GLE960 */ 208 | case 0x2A44: /* Cantiga */ 209 | case 0x2a50: /* Cantiga */ 210 | case 0x2A54: /* Cantiga */ 211 | case 0x2A64: /* Cantiga */ 212 | case 0x2A74: /* Cantiga */ 213 | case 0x2E04: /* Eaglelake */ 214 | case 0x2E14: /* Eaglelake */ 215 | case 0x2E24: /* Eaglelake */ 216 | case 0x2E34: /* Eaglelake */ 217 | case 0x3B64: /* Calpella */ 218 | case 0x3B65: /* Calpella */ 219 | case 0x8C3A: /* Lynx Point H */ 220 | case 0x8CBA: /* Lynx Point H Refresh */ 221 | case 0x8D3A: /* Lynx Point - Wellsburg */ 222 | case 0x9C3A: /* Lynx Point LP */ 223 | case 0x9CBA: /* Wildcat Point LP */ 224 | case 0x9CBB: /* Wildcat Point LP 2 */ 225 | case 0x9D3A: /* Sunrise Point-LP */ 226 | case 0xA13A: /* Sunrise Point-H #1 */ 227 | case 0xA13B: /* Sunrise Point-H #2 */ 228 | case 0xA13E: /* Sunrise Point-H #3 */ 229 | case 0xA1BA: /* CSME Lewisburg #1 */ 230 | case 0xA1BB: /* CSME Lewisburg #2 */ 231 | case 0xA1BE: /* CSME Lewisburg #3 */ 232 | case 0xA1F8: /* IE Lewisburg #1 */ 233 | case 0xA1F9: /* IE Lewisburg #2 */ 234 | case 0xA1FC: /* IE Lewisburg #3 */ 235 | me = 1; 236 | break; 237 | default: 238 | me = 0; 239 | break; 240 | } 241 | } 242 | if (me) break; 243 | } 244 | if (me == 0) { 245 | printf("MEI device not found, huh?\n"); 246 | if (fd2 & 0x2) { 247 | printf("Re-hiding MEI device..."); 248 | fd2 = *(uint32_t *)(rcba + FD2); 249 | *(uint32_t *)(rcba + FD2) = fd2 | 0x2; 250 | printf("done\n"); 251 | } 252 | printf ("exiting\n"); 253 | pci_cleanup(pacc); 254 | munmap((void*)rcba, size); 255 | return 0; 256 | } 257 | 258 | printf("MEI found: [%x:%x] %s\n\n", dev->vendor_id, dev->device_id, name); 259 | stat = pci_read_long(dev, 0x40); 260 | printf("ME Status : 0x%x\n", stat); 261 | stat2 = pci_read_long(dev, 0x48); 262 | printf("ME Status 2 : 0x%x\n\n", stat2); 263 | 264 | intel_me_status(stat, stat2); 265 | printf("\n"); 266 | intel_me_extend_valid(dev); 267 | printf("\n"); 268 | 269 | if ((stat & 0xf000) >> 12 == 0) { 270 | printf("ME seems okay on this board\n"); 271 | } else { 272 | printf("ME has a broken implementation on your board with this BIOS\n"); 273 | } 274 | 275 | intel_mei_setup(dev); 276 | udelay(1000); 277 | mei_reset(); 278 | udelay(10000); 279 | mkhi_get_fw_version(); 280 | udelay(10000); 281 | mei_reset(); 282 | udelay(10000); 283 | mkhi_get_fwcaps(); 284 | udelay(10000); 285 | 286 | /* You need >4GB total ram, in kernel cmdline, use 'mem=1000m' 287 | * then this code will clone to absolute memory address 0xe0000000 288 | * which can be read using a mmap tool at that offset. 289 | * Real ME memory is located around top of memory minus 64MB. (I think) 290 | * so we avoid cloning to this part. 291 | */ 292 | /* 293 | uint32_t me_clone = 0x60000000; 294 | volatile uint8_t *dump; 295 | dump = map_physical_exact(me_clone, me_clone, 0x2000000); 296 | zeroit(dump, 0x2000000); 297 | printf("Send magic command for memory clone\n"); 298 | 299 | mei_reset(); 300 | udelay(10000); 301 | int err = mkhi_debug_me_memory(me_clone); 302 | 303 | if (!err) { 304 | printf("Wait a second..."); 305 | udelay(30000); 306 | printf("done\n\nHere are the first bytes:\n"); 307 | dumpmemfile(dump, 0x2000000); 308 | printf("Try reading 0x%zx with other mmap tool...\n" 309 | "Press enter to quit, you only get one chance to run this tool before reboot required for some reason\n", me_clone); 310 | while (getc(stdin) != '\n') {}; 311 | unmap_physical(dump, 0x2000000); 312 | } 313 | */ 314 | intel_mei_unmap(); 315 | 316 | pci_cleanup(pacc); 317 | 318 | if (fd2 & 0x2) { 319 | printf("Re-hiding MEI device..."); 320 | fd2 = *(uint32_t *)(rcba + FD2); 321 | *(uint32_t *)(rcba + FD2) = fd2 | 0x2; 322 | printf("done, "); 323 | } 324 | printf("exiting\n"); 325 | munmap((void*)rcba, size); 326 | return 0; 327 | } 328 | -------------------------------------------------------------------------------- /intelmetool.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Damien Zammit 3 | * 4 | * This file was created by examining "inteltool" and categorizing chipsets 5 | * by noticing that the Southbridge/LPC device identifies the chipset. 6 | * All PCI IDs in this file should refer to a Southbridge/LPC device. 7 | * It forms most of the detection logic of intelmetool and is subject to 8 | * additions or improvements when new information is available. 9 | * 10 | * Original coreboot "inteltool" work done by: 11 | * Copyright (C) 2008-2010 by coresystems GmbH 12 | * Copyright (C) 2009 Carl-Daniel Hailfinger 13 | * 14 | * This program is free software; you can redistribute it and/or modify 15 | * it under the terms of the GNU General Public License as published by 16 | * the Free Software Foundation; either version 2 of the License 17 | * or (at your option) any later version. 18 | * 19 | * This program is distributed in the hope that it will be useful, 20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | * GNU General Public License for more details. 23 | */ 24 | 25 | #define ME_NOT_PRESENT 0 26 | #define ME_FOUND_NOTHING 1 27 | #define ME_FOUND_SOMETHING_NOT_SURE 2 28 | #define ME_CAN_DISABLE_IF_PRESENT 3 29 | #define ME_PRESENT_CAN_DISABLE 4 30 | #define ME_PRESENT_CANNOT_DISABLE 5 31 | 32 | // If any of the following pci device IDs are found, 33 | // the heading they fall under is the corresponding result. 34 | 35 | // Chipset does not have ME 36 | #define PCI_DEVICE_ID_INTEL_82810 0x7120 37 | #define PCI_DEVICE_ID_INTEL_82810_DC 0x7122 38 | #define PCI_DEVICE_ID_INTEL_82810E_DC 0x7124 39 | #define PCI_DEVICE_ID_INTEL_82830M 0x3575 40 | #define PCI_DEVICE_ID_INTEL_82845 0x1a30 41 | #define PCI_DEVICE_ID_INTEL_82865 0x2570 42 | #define PCI_DEVICE_ID_INTEL_82915 0x2580 43 | #define PCI_DEVICE_ID_INTEL_82945P 0x2770 44 | #define PCI_DEVICE_ID_INTEL_82945GM 0x27a0 45 | #define PCI_DEVICE_ID_INTEL_82945GSE 0x27ac 46 | #define PCI_DEVICE_ID_INTEL_82X58 0x3405 47 | #define PCI_DEVICE_ID_INTEL_ATOM_DXXX 0xa000 48 | #define PCI_DEVICE_ID_INTEL_I63XX 0x2670 49 | #define PCI_DEVICE_ID_INTEL_I5000X 0x25c0 50 | #define PCI_DEVICE_ID_INTEL_I5000Z 0x25d0 51 | #define PCI_DEVICE_ID_INTEL_I5000V 0x25d4 52 | #define PCI_DEVICE_ID_INTEL_I5000P 0x25d8 53 | #define PCI_DEVICE_ID_INTEL_82443LX 0x7180 54 | #define PCI_DEVICE_ID_INTEL_82443BX 0x7190 55 | #define PCI_DEVICE_ID_INTEL_82443BX_NO_AGP 0x7192 56 | #define PCI_DEVICE_ID_INTEL_82371XX 0x7110 57 | #define PCI_DEVICE_ID_INTEL_ICH 0x2410 58 | #define PCI_DEVICE_ID_INTEL_ICH0 0x2420 59 | #define PCI_DEVICE_ID_INTEL_ICH2 0x2440 60 | #define PCI_DEVICE_ID_INTEL_ICH4 0x24c0 61 | #define PCI_DEVICE_ID_INTEL_ICH4M 0x24cc 62 | #define PCI_DEVICE_ID_INTEL_ICH5 0x24d0 63 | #define PCI_DEVICE_ID_INTEL_ICH6 0x2640 64 | #define PCI_DEVICE_ID_INTEL_ICH7DH 0x27b0 65 | #define PCI_DEVICE_ID_INTEL_ICH7 0x27b8 66 | #define PCI_DEVICE_ID_INTEL_ICH7M 0x27b9 67 | #define PCI_DEVICE_ID_INTEL_ICH7MDH 0x27bd 68 | #define PCI_DEVICE_ID_INTEL_NM10 0x27bc 69 | 70 | #define PCI_DEV_NO_ME(x) ( \ 71 | ( (x) == PCI_DEVICE_ID_INTEL_82810 ) || \ 72 | ( (x) == PCI_DEVICE_ID_INTEL_82810_DC ) || \ 73 | ( (x) == PCI_DEVICE_ID_INTEL_82810E_DC ) || \ 74 | ( (x) == PCI_DEVICE_ID_INTEL_82830M ) || \ 75 | ( (x) == PCI_DEVICE_ID_INTEL_82845 ) || \ 76 | ( (x) == PCI_DEVICE_ID_INTEL_82865 ) || \ 77 | ( (x) == PCI_DEVICE_ID_INTEL_82915 ) || \ 78 | ( (x) == PCI_DEVICE_ID_INTEL_82945P ) || \ 79 | ( (x) == PCI_DEVICE_ID_INTEL_82945GM ) || \ 80 | ( (x) == PCI_DEVICE_ID_INTEL_82945GSE ) || \ 81 | ( (x) == PCI_DEVICE_ID_INTEL_82X58 ) || \ 82 | ( (x) == PCI_DEVICE_ID_INTEL_ATOM_DXXX ) || \ 83 | ( (x) == PCI_DEVICE_ID_INTEL_I63XX ) || \ 84 | ( (x) == PCI_DEVICE_ID_INTEL_I5000X ) || \ 85 | ( (x) == PCI_DEVICE_ID_INTEL_I5000Z ) || \ 86 | ( (x) == PCI_DEVICE_ID_INTEL_I5000V ) || \ 87 | ( (x) == PCI_DEVICE_ID_INTEL_I5000P ) || \ 88 | ( (x) == PCI_DEVICE_ID_INTEL_82443LX ) || \ 89 | ( (x) == PCI_DEVICE_ID_INTEL_82443BX ) || \ 90 | ( (x) == PCI_DEVICE_ID_INTEL_82443BX_NO_AGP) || \ 91 | ( (x) == PCI_DEVICE_ID_INTEL_82371XX ) || \ 92 | ( (x) == PCI_DEVICE_ID_INTEL_ICH ) || \ 93 | ( (x) == PCI_DEVICE_ID_INTEL_ICH0 ) || \ 94 | ( (x) == PCI_DEVICE_ID_INTEL_ICH2 ) || \ 95 | ( (x) == PCI_DEVICE_ID_INTEL_ICH4 ) || \ 96 | ( (x) == PCI_DEVICE_ID_INTEL_ICH4M ) || \ 97 | ( (x) == PCI_DEVICE_ID_INTEL_ICH5 ) || \ 98 | ( (x) == PCI_DEVICE_ID_INTEL_ICH6 ) || \ 99 | ( (x) == PCI_DEVICE_ID_INTEL_ICH7DH ) || \ 100 | ( (x) == PCI_DEVICE_ID_INTEL_ICH7 ) || \ 101 | ( (x) == PCI_DEVICE_ID_INTEL_ICH7M ) || \ 102 | ( (x) == PCI_DEVICE_ID_INTEL_ICH7MDH ) || \ 103 | ( (x) == PCI_DEVICE_ID_INTEL_NM10 )) 104 | 105 | 106 | // Definitely has ME and can be disabled 107 | #define PCI_DEVICE_ID_INTEL_ICH8ME 0x2811 108 | #define PCI_DEVICE_ID_INTEL_ICH9ME 0x2917 109 | #define PCI_DEVICE_ID_INTEL_ICH9M 0x2919 110 | 111 | #define PCI_DEV_HAS_ME_DISABLE(x) ( \ 112 | ( (x) == PCI_DEVICE_ID_INTEL_ICH8ME ) || \ 113 | ( (x) == PCI_DEVICE_ID_INTEL_ICH9ME ) || \ 114 | ( (x) == PCI_DEVICE_ID_INTEL_ICH9M )) 115 | 116 | // Definitely has ME and is very difficult to remove 117 | #define PCI_DEVICE_ID_INTEL_ICH10R 0x3a16 118 | #define PCI_DEVICE_ID_INTEL_3400_DESKTOP 0x3b00 119 | #define PCI_DEVICE_ID_INTEL_3400_MOBILE 0x3b01 120 | #define PCI_DEVICE_ID_INTEL_P55 0x3b02 121 | #define PCI_DEVICE_ID_INTEL_PM55 0x3b03 122 | #define PCI_DEVICE_ID_INTEL_H55 0x3b06 123 | #define PCI_DEVICE_ID_INTEL_QM57 0x3b07 124 | #define PCI_DEVICE_ID_INTEL_H57 0x3b08 125 | #define PCI_DEVICE_ID_INTEL_HM55 0x3b09 126 | #define PCI_DEVICE_ID_INTEL_Q57 0x3b0a 127 | #define PCI_DEVICE_ID_INTEL_HM57 0x3b0b 128 | #define PCI_DEVICE_ID_INTEL_3400_MOBILE_SFF 0x3b0d 129 | #define PCI_DEVICE_ID_INTEL_B55_A 0x3b0e 130 | #define PCI_DEVICE_ID_INTEL_QS57 0x3b0f 131 | #define PCI_DEVICE_ID_INTEL_3400 0x3b12 132 | #define PCI_DEVICE_ID_INTEL_3420 0x3b14 133 | #define PCI_DEVICE_ID_INTEL_3450 0x3b16 134 | #define PCI_DEVICE_ID_INTEL_B55_B 0x3b1e 135 | #define PCI_DEVICE_ID_INTEL_Z68 0x1c44 136 | #define PCI_DEVICE_ID_INTEL_P67 0x1c46 137 | #define PCI_DEVICE_ID_INTEL_UM67 0x1c47 138 | #define PCI_DEVICE_ID_INTEL_HM65 0x1c49 139 | #define PCI_DEVICE_ID_INTEL_H67 0x1c4a 140 | #define PCI_DEVICE_ID_INTEL_HM67 0x1c4b 141 | #define PCI_DEVICE_ID_INTEL_Q65 0x1c4c 142 | #define PCI_DEVICE_ID_INTEL_QS67 0x1c4d 143 | #define PCI_DEVICE_ID_INTEL_Q67 0x1c4e 144 | #define PCI_DEVICE_ID_INTEL_QM67 0x1c4f 145 | #define PCI_DEVICE_ID_INTEL_B65 0x1c50 146 | #define PCI_DEVICE_ID_INTEL_C202 0x1c52 147 | #define PCI_DEVICE_ID_INTEL_C204 0x1c54 148 | #define PCI_DEVICE_ID_INTEL_C206 0x1c56 149 | #define PCI_DEVICE_ID_INTEL_H61 0x1c5c 150 | #define PCI_DEVICE_ID_INTEL_Z77 0x1e44 151 | #define PCI_DEVICE_ID_INTEL_Z75 0x1e46 152 | #define PCI_DEVICE_ID_INTEL_Q77 0x1e47 153 | #define PCI_DEVICE_ID_INTEL_Q75 0x1e48 154 | #define PCI_DEVICE_ID_INTEL_B75 0x1e49 155 | #define PCI_DEVICE_ID_INTEL_H77 0x1e4a 156 | #define PCI_DEVICE_ID_INTEL_C216 0x1e53 157 | #define PCI_DEVICE_ID_INTEL_QM77 0x1e55 158 | #define PCI_DEVICE_ID_INTEL_QS77 0x1e56 159 | #define PCI_DEVICE_ID_INTEL_HM77 0x1e57 160 | #define PCI_DEVICE_ID_INTEL_UM77 0x1e58 161 | #define PCI_DEVICE_ID_INTEL_HM76 0x1e59 162 | #define PCI_DEVICE_ID_INTEL_HM75 0x1e5d 163 | #define PCI_DEVICE_ID_INTEL_HM70 0x1e5e 164 | #define PCI_DEVICE_ID_INTEL_NM70 0x1e5f 165 | #define PCI_DEVICE_ID_INTEL_DH89XXCC 0x2310 166 | #define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_FULL 0x9c41 167 | #define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_PREM 0x9c43 168 | #define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_BASE 0x9c45 169 | #define PCI_DEVICE_ID_INTEL_H81 0x8c5c 170 | #define PCI_DEVICE_ID_INTEL_B85 0x8c50 171 | #define PCI_DEVICE_ID_INTEL_Q85 0x8c4c 172 | #define PCI_DEVICE_ID_INTEL_Q87 0x8c4e 173 | #define PCI_DEVICE_ID_INTEL_H87 0x8c4a 174 | #define PCI_DEVICE_ID_INTEL_Z87 0x8c44 175 | #define PCI_DEVICE_ID_INTEL_WILDCAT_LP1 0x9cc1 176 | #define PCI_DEVICE_ID_INTEL_WILDCAT_LP2 0x9cc2 177 | #define PCI_DEVICE_ID_INTEL_WILDCAT_LP3 0x9cc3 178 | #define PCI_DEVICE_ID_INTEL_WILDCAT_LP4 0x9cc5 179 | #define PCI_DEVICE_ID_INTEL_WILDCAT_LP5 0x9cc6 180 | #define PCI_DEVICE_ID_INTEL_WILDCAT_LP6 0x9cc7 181 | #define PCI_DEVICE_ID_INTEL_WILDCAT_LP7 0x9cc9 182 | #define PCI_DEVICE_ID_INTEL_SUNRISE_LP1 0x9d43 183 | #define PCI_DEVICE_ID_INTEL_SUNRISE_LP2 0x9d48 184 | #define PCI_DEVICE_ID_INTEL_SUNRISE_LP3 0x9d4e 185 | #define PCI_DEVICE_ID_INTEL_SUNRISE_LP4 0x9d56 186 | #define PCI_DEVICE_ID_INTEL_SUNRISE_LP5 0x9d58 187 | #define PCI_DEVICE_ID_INTEL_SUNRISE_H0 0xa140 188 | #define PCI_DEVICE_ID_INTEL_SUNRISE_H1 0xa141 189 | #define PCI_DEVICE_ID_INTEL_SUNRISE_H2 0xa142 190 | #define PCI_DEVICE_ID_INTEL_SUNRISE_H3 0xa143 191 | #define PCI_DEVICE_ID_INTEL_SUNRISE_H4 0xa144 192 | #define PCI_DEVICE_ID_INTEL_SUNRISE_H5 0xa145 193 | #define PCI_DEVICE_ID_INTEL_SUNRISE_H6 0xa146 194 | #define PCI_DEVICE_ID_INTEL_SUNRISE_H7 0xa147 195 | #define PCI_DEVICE_ID_INTEL_SUNRISE_H8 0xa148 196 | #define PCI_DEVICE_ID_INTEL_SUNRISE_H9 0xa149 197 | #define PCI_DEVICE_ID_INTEL_SUNRISE_H10 0xa14a 198 | #define PCI_DEVICE_ID_INTEL_SUNRISE_H11 0xa14b 199 | #define PCI_DEVICE_ID_INTEL_SUNRISE_H12 0xa14c 200 | #define PCI_DEVICE_ID_INTEL_SUNRISE_H13 0xa14d 201 | #define PCI_DEVICE_ID_INTEL_SUNRISE_H14 0xa14e 202 | #define PCI_DEVICE_ID_INTEL_SUNRISE_H15 0xa14f 203 | #define PCI_DEVICE_ID_INTEL_SUNRISE_H16 0xa150 204 | #define PCI_DEVICE_ID_INTEL_SUNRISE_H17 0xa151 205 | #define PCI_DEVICE_ID_INTEL_SUNRISE_H18 0xa152 206 | #define PCI_DEVICE_ID_INTEL_SUNRISE_H19 0xa153 207 | #define PCI_DEVICE_ID_INTEL_SUNRISE_H20 0xa154 208 | #define PCI_DEVICE_ID_INTEL_SUNRISE_H21 0xa155 209 | #define PCI_DEVICE_ID_INTEL_SUNRISE_H22 0xa156 210 | #define PCI_DEVICE_ID_INTEL_SUNRISE_H23 0xa157 211 | #define PCI_DEVICE_ID_INTEL_SUNRISE_H24 0xa158 212 | #define PCI_DEVICE_ID_INTEL_SUNRISE_H25 0xa159 213 | #define PCI_DEVICE_ID_INTEL_SUNRISE_H26 0xa15a 214 | #define PCI_DEVICE_ID_INTEL_SUNRISE_H27 0xa15b 215 | #define PCI_DEVICE_ID_INTEL_SUNRISE_H28 0xa15c 216 | #define PCI_DEVICE_ID_INTEL_SUNRISE_H29 0xa15d 217 | #define PCI_DEVICE_ID_INTEL_SUNRISE_H30 0xa15e 218 | #define PCI_DEVICE_ID_INTEL_SUNRISE_H31 0xa15f 219 | #define PCI_DEVICE_ID_INTEL_LEWISBURG_1 0xa1c1 220 | #define PCI_DEVICE_ID_INTEL_LEWISBURG_2 0xa1c2 221 | #define PCI_DEVICE_ID_INTEL_LEWISBURG_3 0xa1c3 222 | #define PCI_DEVICE_ID_INTEL_LEWISBURG_4 0xa1c4 223 | #define PCI_DEVICE_ID_INTEL_LEWISBURG_5 0xa1c5 224 | #define PCI_DEVICE_ID_INTEL_LEWISBURG_6 0xa1c6 225 | #define PCI_DEVICE_ID_INTEL_LEWISBURG_7 0xa1c7 226 | 227 | #define PCI_DEV_HAS_ME_DIFFICULT(x) ( \ 228 | ( (x) == PCI_DEVICE_ID_INTEL_ICH10R ) || \ 229 | ( (x) == PCI_DEVICE_ID_INTEL_3400_DESKTOP ) || \ 230 | ( (x) == PCI_DEVICE_ID_INTEL_3400_MOBILE ) || \ 231 | ( (x) == PCI_DEVICE_ID_INTEL_P55 ) || \ 232 | ( (x) == PCI_DEVICE_ID_INTEL_PM55 ) || \ 233 | ( (x) == PCI_DEVICE_ID_INTEL_H55 ) || \ 234 | ( (x) == PCI_DEVICE_ID_INTEL_QM57 ) || \ 235 | ( (x) == PCI_DEVICE_ID_INTEL_H57 ) || \ 236 | ( (x) == PCI_DEVICE_ID_INTEL_HM55 ) || \ 237 | ( (x) == PCI_DEVICE_ID_INTEL_Q57 ) || \ 238 | ( (x) == PCI_DEVICE_ID_INTEL_HM57 ) || \ 239 | ( (x) == PCI_DEVICE_ID_INTEL_3400_MOBILE_SFF ) || \ 240 | ( (x) == PCI_DEVICE_ID_INTEL_B55_A ) || \ 241 | ( (x) == PCI_DEVICE_ID_INTEL_QS57 ) || \ 242 | ( (x) == PCI_DEVICE_ID_INTEL_3400 ) || \ 243 | ( (x) == PCI_DEVICE_ID_INTEL_3420 ) || \ 244 | ( (x) == PCI_DEVICE_ID_INTEL_3450 ) || \ 245 | ( (x) == PCI_DEVICE_ID_INTEL_B55_B ) || \ 246 | ( (x) == PCI_DEVICE_ID_INTEL_Z68 ) || \ 247 | ( (x) == PCI_DEVICE_ID_INTEL_P67 ) || \ 248 | ( (x) == PCI_DEVICE_ID_INTEL_UM67 ) || \ 249 | ( (x) == PCI_DEVICE_ID_INTEL_HM65 ) || \ 250 | ( (x) == PCI_DEVICE_ID_INTEL_H67 ) || \ 251 | ( (x) == PCI_DEVICE_ID_INTEL_HM67 ) || \ 252 | ( (x) == PCI_DEVICE_ID_INTEL_Q65 ) || \ 253 | ( (x) == PCI_DEVICE_ID_INTEL_QS67 ) || \ 254 | ( (x) == PCI_DEVICE_ID_INTEL_Q67 ) || \ 255 | ( (x) == PCI_DEVICE_ID_INTEL_QM67 ) || \ 256 | ( (x) == PCI_DEVICE_ID_INTEL_B65 ) || \ 257 | ( (x) == PCI_DEVICE_ID_INTEL_C202 ) || \ 258 | ( (x) == PCI_DEVICE_ID_INTEL_C204 ) || \ 259 | ( (x) == PCI_DEVICE_ID_INTEL_C206 ) || \ 260 | ( (x) == PCI_DEVICE_ID_INTEL_H61 ) || \ 261 | ( (x) == PCI_DEVICE_ID_INTEL_Z77 ) || \ 262 | ( (x) == PCI_DEVICE_ID_INTEL_Z75 ) || \ 263 | ( (x) == PCI_DEVICE_ID_INTEL_Q77 ) || \ 264 | ( (x) == PCI_DEVICE_ID_INTEL_Q75 ) || \ 265 | ( (x) == PCI_DEVICE_ID_INTEL_B75 ) || \ 266 | ( (x) == PCI_DEVICE_ID_INTEL_H77 ) || \ 267 | ( (x) == PCI_DEVICE_ID_INTEL_C216 ) || \ 268 | ( (x) == PCI_DEVICE_ID_INTEL_QM77 ) || \ 269 | ( (x) == PCI_DEVICE_ID_INTEL_QS77 ) || \ 270 | ( (x) == PCI_DEVICE_ID_INTEL_HM77 ) || \ 271 | ( (x) == PCI_DEVICE_ID_INTEL_UM77 ) || \ 272 | ( (x) == PCI_DEVICE_ID_INTEL_HM76 ) || \ 273 | ( (x) == PCI_DEVICE_ID_INTEL_HM75 ) || \ 274 | ( (x) == PCI_DEVICE_ID_INTEL_HM70 ) || \ 275 | ( (x) == PCI_DEVICE_ID_INTEL_NM70 ) || \ 276 | ( (x) == PCI_DEVICE_ID_INTEL_DH89XXCC ) || \ 277 | ( (x) == PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_FULL ) || \ 278 | ( (x) == PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_PREM ) || \ 279 | ( (x) == PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_BASE ) || \ 280 | ( (x) == PCI_DEVICE_ID_INTEL_H81 ) || \ 281 | ( (x) == PCI_DEVICE_ID_INTEL_B85 ) || \ 282 | ( (x) == PCI_DEVICE_ID_INTEL_Q85 ) || \ 283 | ( (x) == PCI_DEVICE_ID_INTEL_Q87 ) || \ 284 | ( (x) == PCI_DEVICE_ID_INTEL_H87 ) || \ 285 | ( (x) == PCI_DEVICE_ID_INTEL_Z87 ) || \ 286 | ( (x) == PCI_DEVICE_ID_INTEL_WILDCAT_LP1 ) || \ 287 | ( (x) == PCI_DEVICE_ID_INTEL_WILDCAT_LP2 ) || \ 288 | ( (x) == PCI_DEVICE_ID_INTEL_WILDCAT_LP3 ) || \ 289 | ( (x) == PCI_DEVICE_ID_INTEL_WILDCAT_LP4 ) || \ 290 | ( (x) == PCI_DEVICE_ID_INTEL_WILDCAT_LP5 ) || \ 291 | ( (x) == PCI_DEVICE_ID_INTEL_WILDCAT_LP6 ) || \ 292 | ( (x) == PCI_DEVICE_ID_INTEL_WILDCAT_LP7 ) || \ 293 | ( (x) == PCI_DEVICE_ID_INTEL_SUNRISE_LP1 ) || \ 294 | ( (x) == PCI_DEVICE_ID_INTEL_SUNRISE_LP2 ) || \ 295 | ( (x) == PCI_DEVICE_ID_INTEL_SUNRISE_LP3 ) || \ 296 | ( (x) == PCI_DEVICE_ID_INTEL_SUNRISE_LP4 ) || \ 297 | ( (x) == PCI_DEVICE_ID_INTEL_SUNRISE_LP5 ) || \ 298 | ( (x) == PCI_DEVICE_ID_INTEL_SUNRISE_H0 ) || \ 299 | ( (x) == PCI_DEVICE_ID_INTEL_SUNRISE_H1 ) || \ 300 | ( (x) == PCI_DEVICE_ID_INTEL_SUNRISE_H2 ) || \ 301 | ( (x) == PCI_DEVICE_ID_INTEL_SUNRISE_H3 ) || \ 302 | ( (x) == PCI_DEVICE_ID_INTEL_SUNRISE_H4 ) || \ 303 | ( (x) == PCI_DEVICE_ID_INTEL_SUNRISE_H5 ) || \ 304 | ( (x) == PCI_DEVICE_ID_INTEL_SUNRISE_H6 ) || \ 305 | ( (x) == PCI_DEVICE_ID_INTEL_SUNRISE_H7 ) || \ 306 | ( (x) == PCI_DEVICE_ID_INTEL_SUNRISE_H8 ) || \ 307 | ( (x) == PCI_DEVICE_ID_INTEL_SUNRISE_H9 ) || \ 308 | ( (x) == PCI_DEVICE_ID_INTEL_SUNRISE_H10 ) || \ 309 | ( (x) == PCI_DEVICE_ID_INTEL_SUNRISE_H11 ) || \ 310 | ( (x) == PCI_DEVICE_ID_INTEL_SUNRISE_H12 ) || \ 311 | ( (x) == PCI_DEVICE_ID_INTEL_SUNRISE_H13 ) || \ 312 | ( (x) == PCI_DEVICE_ID_INTEL_SUNRISE_H14 ) || \ 313 | ( (x) == PCI_DEVICE_ID_INTEL_SUNRISE_H15 ) || \ 314 | ( (x) == PCI_DEVICE_ID_INTEL_SUNRISE_H16 ) || \ 315 | ( (x) == PCI_DEVICE_ID_INTEL_SUNRISE_H17 ) || \ 316 | ( (x) == PCI_DEVICE_ID_INTEL_SUNRISE_H18 ) || \ 317 | ( (x) == PCI_DEVICE_ID_INTEL_SUNRISE_H19 ) || \ 318 | ( (x) == PCI_DEVICE_ID_INTEL_SUNRISE_H20 ) || \ 319 | ( (x) == PCI_DEVICE_ID_INTEL_SUNRISE_H21 ) || \ 320 | ( (x) == PCI_DEVICE_ID_INTEL_SUNRISE_H22 ) || \ 321 | ( (x) == PCI_DEVICE_ID_INTEL_SUNRISE_H23 ) || \ 322 | ( (x) == PCI_DEVICE_ID_INTEL_SUNRISE_H24 ) || \ 323 | ( (x) == PCI_DEVICE_ID_INTEL_SUNRISE_H25 ) || \ 324 | ( (x) == PCI_DEVICE_ID_INTEL_SUNRISE_H26 ) || \ 325 | ( (x) == PCI_DEVICE_ID_INTEL_SUNRISE_H27 ) || \ 326 | ( (x) == PCI_DEVICE_ID_INTEL_SUNRISE_H28 ) || \ 327 | ( (x) == PCI_DEVICE_ID_INTEL_SUNRISE_H29 ) || \ 328 | ( (x) == PCI_DEVICE_ID_INTEL_SUNRISE_H30 ) || \ 329 | ( (x) == PCI_DEVICE_ID_INTEL_SUNRISE_H31 ) || \ 330 | ( (x) == PCI_DEVICE_ID_INTEL_LEWISBURG_1 ) || \ 331 | ( (x) == PCI_DEVICE_ID_INTEL_LEWISBURG_2 ) || \ 332 | ( (x) == PCI_DEVICE_ID_INTEL_LEWISBURG_3 ) || \ 333 | ( (x) == PCI_DEVICE_ID_INTEL_LEWISBURG_4 ) || \ 334 | ( (x) == PCI_DEVICE_ID_INTEL_LEWISBURG_5 ) || \ 335 | ( (x) == PCI_DEVICE_ID_INTEL_LEWISBURG_6 ) || \ 336 | ( (x) == PCI_DEVICE_ID_INTEL_LEWISBURG_7 ) || \ 337 | 0) 338 | 339 | // Not sure if ME present, but should be able to disable it easily 340 | #define PCI_DEVICE_ID_INTEL_ICH8 0x2810 341 | #define PCI_DEVICE_ID_INTEL_ICH8M 0x2815 342 | #define PCI_DEVICE_ID_INTEL_ICH9DH 0x2912 343 | #define PCI_DEVICE_ID_INTEL_ICH9DO 0x2914 344 | #define PCI_DEVICE_ID_INTEL_ICH9R 0x2916 345 | #define PCI_DEVICE_ID_INTEL_ICH9 0x2918 346 | 347 | #define PCI_DEV_CAN_DISABLE_ME_IF_PRESENT(x) ( \ 348 | ( (x) == PCI_DEVICE_ID_INTEL_ICH8 ) || \ 349 | ( (x) == PCI_DEVICE_ID_INTEL_ICH8M ) || \ 350 | ( (x) == PCI_DEVICE_ID_INTEL_ICH9DH ) || \ 351 | ( (x) == PCI_DEVICE_ID_INTEL_ICH9DO ) || \ 352 | ( (x) == PCI_DEVICE_ID_INTEL_ICH9R ) || \ 353 | ( (x) == PCI_DEVICE_ID_INTEL_ICH9 )) 354 | 355 | // Not sure at all 356 | #define PCI_DEVICE_ID_INTEL_SCH_POULSBO_LPC 0x8119 357 | #define PCI_DEVICE_ID_INTEL_SCH_POULSBO 0x8100 358 | 359 | #define PCI_DEV_ME_NOT_SURE(x) ( \ 360 | ( (x) == PCI_DEVICE_ID_INTEL_SCH_POULSBO_LPC ) || \ 361 | ( (x) == PCI_DEVICE_ID_INTEL_SCH_POULSBO)) 362 | -------------------------------------------------------------------------------- /me.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the coreboot project. 3 | * 4 | * Copyright (C) 2011 The Chromium OS Authors. All rights reserved. 5 | * Copyright (C) 2013 Damien Zammit 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; version 2 of 10 | * the License. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, 20 | * MA 02110-1301 USA 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include "me.h" 30 | #include "mmap.h" 31 | 32 | #define read32(addr, off) ( *((uint32_t *) (addr + off)) ) 33 | #define write32(addr, off, val) ( *((uint32_t *) (addr + off)) = val) 34 | 35 | // FIXME: define this for old firmware only 36 | //#define OLDARC 1 37 | 38 | void udelay(uint32_t usecs) 39 | { 40 | int i; 41 | for(i = 0; i < usecs; i++) 42 | inb(0x80); 43 | } 44 | 45 | /* Path that the BIOS should take based on ME state */ 46 | /* 47 | static const char *me_bios_path_values[] = { 48 | [ME_NORMAL_BIOS_PATH] = "Normal", 49 | [ME_S3WAKE_BIOS_PATH] = "S3 Wake", 50 | [ME_ERROR_BIOS_PATH] = "Error", 51 | [ME_RECOVERY_BIOS_PATH] = "Recovery", 52 | [ME_DISABLE_BIOS_PATH] = "Disable", 53 | [ME_FIRMWARE_UPDATE_BIOS_PATH] = "Firmware Update", 54 | }; 55 | */ 56 | 57 | /* MMIO base address for MEI interface */ 58 | static uint32_t mei_base_address; 59 | static uint8_t* mei_mmap; 60 | 61 | #if 1 62 | static void mei_dump(void *ptr, int dword, int offset, const char *type) 63 | { 64 | struct mei_csr *csr; 65 | 66 | 67 | switch (offset) { 68 | case MEI_H_CSR: 69 | case MEI_ME_CSR_HA: 70 | csr = ptr; 71 | /* if (!csr) { 72 | printf("%-9s[%02x] : ", type, offset); 73 | printf("ERROR: 0x%08x\n", dword); 74 | break; 75 | } 76 | printf("%-9s[%02x] : ", type, offset); 77 | printf("depth=%u read=%02u write=%02u ready=%u " 78 | "reset=%u intgen=%u intstatus=%u intenable=%u\n", csr->buffer_depth, 79 | csr->buffer_read_ptr, csr->buffer_write_ptr, 80 | csr->ready, csr->reset, csr->interrupt_generate, 81 | csr->interrupt_status, csr->interrupt_enable); 82 | */ break; 83 | case MEI_ME_CB_RW: 84 | case MEI_H_CB_WW: 85 | printf("%-9s[%02x] : ", type, offset); 86 | printf("CB: 0x%08x\n", dword); 87 | break; 88 | default: 89 | printf("%-9s[%02x] : ", type, offset); 90 | printf("0x%08x\n", offset); 91 | break; 92 | } 93 | } 94 | #else 95 | # define mei_dump(ptr,dword,offset,type) do {} while (0) 96 | #endif 97 | 98 | /* 99 | * ME/MEI access helpers using memcpy to avoid aliasing. 100 | */ 101 | 102 | static inline void mei_read_dword_ptr(void *ptr, uint32_t offset) 103 | { 104 | uint32_t dword = read32(mei_mmap, offset); 105 | memcpy(ptr, &dword, sizeof(dword)); 106 | mei_dump(ptr, dword, offset, "READ"); 107 | } 108 | 109 | static inline void mei_write_dword_ptr(void *ptr, uint32_t offset) 110 | { 111 | uint32_t dword = 0; 112 | memcpy(&dword, ptr, sizeof(dword)); 113 | write32(mei_mmap, offset, dword); 114 | mei_dump(ptr, dword, offset, "WRITE"); 115 | } 116 | 117 | static inline void pci_read_dword_ptr(struct pci_dev *dev, void *ptr, uint32_t offset) 118 | { 119 | uint32_t dword = pci_read_long(dev, offset); 120 | memcpy(ptr, &dword, sizeof(dword)); 121 | mei_dump(ptr, dword, offset, "PCI READ"); 122 | } 123 | 124 | static inline void read_host_csr(struct mei_csr *csr) 125 | { 126 | mei_read_dword_ptr(csr, MEI_H_CSR); 127 | } 128 | 129 | static inline void write_host_csr(struct mei_csr *csr) 130 | { 131 | mei_write_dword_ptr(csr, MEI_H_CSR); 132 | } 133 | 134 | static inline void read_me_csr(struct mei_csr *csr) 135 | { 136 | mei_read_dword_ptr(csr, MEI_ME_CSR_HA); 137 | } 138 | 139 | static inline void write_cb(uint32_t dword) 140 | { 141 | write32(mei_mmap, MEI_H_CB_WW, dword); 142 | mei_dump(NULL, dword, MEI_H_CB_WW, "WRITE"); 143 | } 144 | 145 | static inline uint32_t read_cb(void) 146 | { 147 | uint32_t dword = read32(mei_mmap, MEI_ME_CB_RW); 148 | mei_dump(NULL, dword, MEI_ME_CB_RW, "READ"); 149 | return dword; 150 | } 151 | 152 | /* Wait for ME ready bit to be asserted */ 153 | static int mei_wait_for_me_ready(void) 154 | { 155 | struct mei_csr me; 156 | unsigned try = ME_RETRY; 157 | 158 | while (try--) { 159 | read_me_csr(&me); 160 | if (me.ready) 161 | return 0; 162 | udelay(ME_DELAY); 163 | } 164 | 165 | printf("ME: failed to become ready\n"); 166 | return -1; 167 | } 168 | 169 | void mei_reset(void) 170 | { 171 | struct mei_csr host; 172 | 173 | if (mei_wait_for_me_ready() < 0) 174 | return; 175 | 176 | /* Reset host and ME circular buffers for next message */ 177 | read_host_csr(&host); 178 | host.reset = 1; 179 | host.interrupt_generate = 1; 180 | write_host_csr(&host); 181 | 182 | if (mei_wait_for_me_ready() < 0) 183 | return; 184 | 185 | /* Re-init and indicate host is ready */ 186 | read_host_csr(&host); 187 | host.interrupt_generate = 1; 188 | host.ready = 1; 189 | host.reset = 0; 190 | write_host_csr(&host); 191 | } 192 | 193 | static int mei_send_msg(struct mei_header *mei, struct mkhi_header *mkhi, 194 | void *req_data) 195 | { 196 | struct mei_csr host; 197 | unsigned ndata, n; 198 | uint32_t *data; 199 | 200 | /* Number of dwords to write, ignoring MKHI */ 201 | ndata = (mei->length) >> 2; 202 | 203 | /* Pad non-dword aligned request message length */ 204 | if (mei->length & 3) 205 | ndata++; 206 | if (!ndata) { 207 | printf("ME: request does not include MKHI\n"); 208 | return -1; 209 | } 210 | ndata++; /* Add MEI header */ 211 | 212 | /* 213 | * Make sure there is still room left in the circular buffer. 214 | * Reset the buffer pointers if the requested message will not fit. 215 | */ 216 | read_host_csr(&host); 217 | if ((host.buffer_depth - host.buffer_write_ptr) < ndata) { 218 | printf("ME: circular buffer full, resetting...\n"); 219 | mei_reset(); 220 | read_host_csr(&host); 221 | } 222 | 223 | /* 224 | * This implementation does not handle splitting large messages 225 | * across multiple transactions. Ensure the requested length 226 | * will fit in the available circular buffer depth. 227 | */ 228 | if ((host.buffer_depth - host.buffer_write_ptr) < ndata) { 229 | printf("ME: message (%u) too large for buffer (%u)\n", 230 | ndata + 2, host.buffer_depth); 231 | return -1; 232 | } 233 | 234 | /* Write MEI header */ 235 | mei_write_dword_ptr(mei, MEI_H_CB_WW); 236 | ndata--; 237 | 238 | /* Write MKHI header */ 239 | mei_write_dword_ptr(mkhi, MEI_H_CB_WW); 240 | ndata--; 241 | 242 | /* Write message data */ 243 | data = req_data; 244 | for (n = 0; n < ndata; ++n) 245 | write_cb(*data++); 246 | 247 | /* Generate interrupt to the ME */ 248 | read_host_csr(&host); 249 | host.interrupt_generate = 1; 250 | write_host_csr(&host); 251 | 252 | /* Make sure ME is ready after sending request data */ 253 | return mei_wait_for_me_ready(); 254 | } 255 | 256 | static int mei_recv_msg(struct mei_header *mei, struct mkhi_header *mkhi, 257 | void *rsp_data, uint32_t rsp_bytes) 258 | { 259 | struct mei_header mei_rsp; 260 | struct mkhi_header mkhi_rsp; 261 | struct mei_csr me, host; 262 | unsigned ndata, n; 263 | unsigned expected; 264 | uint32_t *data; 265 | 266 | /* Total number of dwords to read from circular buffer */ 267 | expected = (rsp_bytes + sizeof(mei_rsp) + sizeof(mkhi_rsp)) >> 2; 268 | if (rsp_bytes & 3) 269 | expected++; 270 | 271 | //printf("expected u32 = %d\n", expected); 272 | /* 273 | * The interrupt status bit does not appear to indicate that the 274 | * message has actually been received. Instead we wait until the 275 | * expected number of dwords are present in the circular buffer. 276 | */ 277 | for (n = ME_RETRY; n; --n) { 278 | read_me_csr(&me); 279 | if ((me.buffer_write_ptr - me.buffer_read_ptr) >= expected) 280 | //if (me.interrupt_generate && !me.interrupt_status) 281 | //if (me.interrupt_status) 282 | break; 283 | udelay(ME_DELAY); 284 | } 285 | if (!n) { 286 | printf("ME: timeout waiting for data: expected " 287 | "%u, available %u\n", expected, 288 | me.buffer_write_ptr - me.buffer_read_ptr); 289 | return -1; 290 | } 291 | /* Read and verify MEI response header from the ME */ 292 | mei_read_dword_ptr(&mei_rsp, MEI_ME_CB_RW); 293 | if (!mei_rsp.is_complete) { 294 | printf("ME: response is not complete\n"); 295 | return -1; 296 | } 297 | 298 | /* Handle non-dword responses and expect at least MKHI header */ 299 | ndata = mei_rsp.length >> 2; 300 | if (mei_rsp.length & 3) 301 | ndata++; 302 | if (ndata != (expected - 1)) { //XXX 303 | printf("ME: response is missing data\n"); 304 | //return -1; 305 | } 306 | 307 | /* Read and verify MKHI response header from the ME */ 308 | mei_read_dword_ptr(&mkhi_rsp, MEI_ME_CB_RW); 309 | if (!mkhi_rsp.is_response || 310 | mkhi->group_id != mkhi_rsp.group_id || 311 | mkhi->command != mkhi_rsp.command) { 312 | printf("ME: invalid response, group %u ?= %u, " 313 | "command %u ?= %u, is_response %u\n", mkhi->group_id, 314 | mkhi_rsp.group_id, mkhi->command, mkhi_rsp.command, 315 | mkhi_rsp.is_response); 316 | //return -1; 317 | } 318 | ndata--; /* MKHI header has been read */ 319 | 320 | /* Make sure caller passed a buffer with enough space */ 321 | if (ndata != (rsp_bytes >> 2)) { 322 | printf("ME: not enough room in response buffer: " 323 | "%u != %u\n", ndata, rsp_bytes >> 2); 324 | //return -1; 325 | } 326 | 327 | /* Read response data from the circular buffer */ 328 | data = rsp_data; 329 | for (n = 0; n < ndata; ++n) 330 | *data++ = read_cb(); 331 | 332 | /* Tell the ME that we have consumed the response */ 333 | read_host_csr(&host); 334 | host.interrupt_status = 1; 335 | host.interrupt_generate = 1; 336 | write_host_csr(&host); 337 | 338 | return mei_wait_for_me_ready(); 339 | } 340 | 341 | static inline int mei_sendrecv(struct mei_header *mei, struct mkhi_header *mkhi, 342 | void *req_data, void *rsp_data, uint32_t rsp_bytes) 343 | { 344 | if (mei_send_msg(mei, mkhi, req_data) < 0) 345 | return -1; 346 | if (mei_recv_msg(mei, mkhi, rsp_data, rsp_bytes) < 0) 347 | return -1; 348 | return 0; 349 | } 350 | 351 | /* Send END OF POST message to the ME */ 352 | /* 353 | static int mkhi_end_of_post(void) 354 | { 355 | struct mkhi_header mkhi = { 356 | .group_id = MKHI_GROUP_ID_GEN, 357 | .command = MKHI_END_OF_POST, 358 | }; 359 | struct mei_header mei = { 360 | .is_complete = 1, 361 | .host_address = MEI_HOST_ADDRESS, 362 | .client_address = MEI_ADDRESS_MKHI, 363 | .length = sizeof(mkhi), 364 | }; 365 | 366 | if (mei_sendrecv(&mei, &mkhi, NULL, NULL, 0) < 0) { 367 | printf("ME: END OF POST message failed\n"); 368 | return -1; 369 | } 370 | 371 | printf("ME: END OF POST message successful\n"); 372 | return 0; 373 | } 374 | */ 375 | 376 | /* Get ME firmware version */ 377 | int mkhi_get_fw_version(void) 378 | { 379 | uint32_t data = 0; 380 | struct me_fw_version version = {0}; 381 | 382 | struct mkhi_header mkhi = { 383 | .group_id = MKHI_GROUP_ID_GEN, 384 | .command = GEN_GET_FW_VERSION, 385 | .is_response = 0, 386 | }; 387 | 388 | struct mei_header mei = { 389 | .is_complete = 1, 390 | .host_address = MEI_HOST_ADDRESS, 391 | .client_address = MEI_ADDRESS_MKHI, 392 | .length = sizeof(mkhi), 393 | }; 394 | 395 | #ifndef OLDARC 396 | /* Send request and wait for response */ 397 | if (mei_sendrecv(&mei, &mkhi, &data, &version, sizeof(version) ) < 0) { 398 | printf("ME: GET FW VERSION message failed\n"); 399 | return -1; 400 | } 401 | printf("ME: Firmware Version %u.%u.%u.%u (code) " 402 | "%u.%u.%u.%u (recovery) " 403 | "%u.%u.%u.%u (fitc)\n", 404 | version.code_major, version.code_minor, 405 | version.code_build_number, version.code_hot_fix, 406 | version.recovery_major, version.recovery_minor, 407 | version.recovery_build_number, version.recovery_hot_fix, 408 | version.fitcmajor, version.fitcminor, 409 | version.fitcbuildno, version.fitchotfix); 410 | #else 411 | /* Send request and wait for response */ 412 | if (mei_sendrecv(&mei, &mkhi, &data, &version, 2*sizeof(uint32_t) ) < 0) { 413 | printf("ME: GET FW VERSION message failed\n"); 414 | return -1; 415 | } 416 | printf("ME: Firmware Version %u.%u (code)\n" 417 | version.code_major, version.code_minor); 418 | #endif 419 | return 0; 420 | } 421 | 422 | static inline void print_cap(const char *name, int state) 423 | { 424 | printf("ME Capability: %-30s : %s\n", 425 | name, state ? "ON" : "OFF"); 426 | } 427 | 428 | /* Get ME Firmware Capabilities */ 429 | int mkhi_get_fwcaps(void) 430 | { 431 | struct { 432 | uint32_t rule_id; 433 | uint32_t rule_len; 434 | 435 | struct me_fwcaps cap; 436 | } fwcaps; 437 | 438 | fwcaps.rule_id = 0; 439 | fwcaps.rule_len = 0; 440 | 441 | struct mkhi_header mkhi = { 442 | .group_id = MKHI_GROUP_ID_FWCAPS, 443 | .command = MKHI_FWCAPS_GET_RULE, 444 | .is_response = 0, 445 | }; 446 | struct mei_header mei = { 447 | .is_complete = 1, 448 | .host_address = MEI_HOST_ADDRESS, 449 | .client_address = MEI_ADDRESS_MKHI, 450 | .length = sizeof(mkhi) + sizeof(fwcaps.rule_id), 451 | }; 452 | 453 | /* Send request and wait for response */ 454 | if (mei_sendrecv(&mei, &mkhi, &fwcaps.rule_id, &fwcaps.cap, sizeof(fwcaps.cap)) < 0) { 455 | printf("ME: GET FWCAPS message failed\n"); 456 | return -1; 457 | } 458 | 459 | print_cap("Full Network manageability ", fwcaps.cap.caps_sku.full_net); 460 | print_cap("Regular Network manageability ", fwcaps.cap.caps_sku.std_net); 461 | print_cap("Manageability ", fwcaps.cap.caps_sku.manageability); 462 | print_cap("Small business technology ", fwcaps.cap.caps_sku.small_business); 463 | print_cap("Level III manageability ", fwcaps.cap.caps_sku.l3manageability); 464 | print_cap("IntelR Anti-Theft (AT) ", fwcaps.cap.caps_sku.intel_at); 465 | print_cap("IntelR Capability Licensing Service (CLS) ", 466 | fwcaps.cap.caps_sku.intel_cls); 467 | print_cap("IntelR Power Sharing Technology (MPC) ", 468 | fwcaps.cap.caps_sku.intel_mpc); 469 | print_cap("ICC Over Clocking ", fwcaps.cap.caps_sku.icc_over_clocking); 470 | print_cap("Protected Audio Video Path (PAVP) ", fwcaps.cap.caps_sku.pavp); 471 | print_cap("IPV6 ", fwcaps.cap.caps_sku.ipv6); 472 | print_cap("KVM Remote Control (KVM) ", fwcaps.cap.caps_sku.kvm); 473 | print_cap("Outbreak Containment Heuristic (OCH) ", fwcaps.cap.caps_sku.och); 474 | print_cap("Virtual LAN (VLAN) ", fwcaps.cap.caps_sku.vlan); 475 | print_cap("TLS ", fwcaps.cap.caps_sku.tls); 476 | print_cap("Wireless LAN (WLAN) ", fwcaps.cap.caps_sku.wlan); 477 | 478 | return 0; 479 | } 480 | 481 | /* Tell ME to issue a global reset */ 482 | uint32_t mkhi_global_reset(void) 483 | { 484 | struct me_global_reset reset = { 485 | .request_origin = GLOBAL_RESET_BIOS_POST, 486 | .reset_type = CBM_RR_GLOBAL_RESET, 487 | }; 488 | struct mkhi_header mkhi = { 489 | .group_id = MKHI_GROUP_ID_CBM, 490 | .command = MKHI_GLOBAL_RESET, 491 | }; 492 | struct mei_header mei = { 493 | .is_complete = 1, 494 | .length = sizeof(mkhi) + sizeof(reset), 495 | .host_address = MEI_HOST_ADDRESS, 496 | .client_address = MEI_ADDRESS_MKHI, 497 | }; 498 | 499 | printf("ME: Requesting global reset\n"); 500 | 501 | /* Send request and wait for response */ 502 | if (mei_sendrecv(&mei, &mkhi, &reset, NULL, 0) < 0) { 503 | /* No response means reset will happen shortly... */ 504 | asm("hlt"); 505 | } 506 | 507 | /* If the ME responded it rejected the reset request */ 508 | printf("ME: Global Reset failed\n"); 509 | return -1; 510 | } 511 | 512 | /* Tell ME thermal reporting parameters */ 513 | /* 514 | void mkhi_thermal(void) 515 | { 516 | struct me_thermal_reporting thermal = { 517 | .polling_timeout = 2, 518 | .smbus_ec_msglen = 1, 519 | .smbus_ec_msgpec = 0, 520 | .dimmnumber = 4, 521 | }; 522 | struct mkhi_header mkhi = { 523 | .group_id = MKHI_GROUP_ID_CBM, 524 | .command = MKHI_THERMAL_REPORTING, 525 | }; 526 | struct mei_header mei = { 527 | .is_complete = 1, 528 | .length = sizeof(mkhi) + sizeof(thermal), 529 | .host_address = MEI_HOST_ADDRESS, 530 | .client_address = MEI_ADDRESS_THERMAL, 531 | }; 532 | 533 | printf("ME: Sending thermal reporting params\n"); 534 | 535 | mei_sendrecv(&mei, &mkhi, &thermal, NULL, 0); 536 | } 537 | */ 538 | 539 | /* Enable debug of internal ME memory */ 540 | int mkhi_debug_me_memory(void *physaddr) 541 | { 542 | uint32_t data = 0; 543 | 544 | /* copy whole ME memory to a readable space */ 545 | struct me_debug_mem memory = { 546 | .debug_phys = (uintptr_t)physaddr, 547 | .debug_size = 0x2000000, 548 | .me_phys = 0x20000000, 549 | .me_size = 0x2000000, 550 | }; 551 | struct mkhi_header mkhi = { 552 | .group_id = MKHI_GROUP_ID_GEN, 553 | .command = GEN_SET_DEBUG_MEM, 554 | .is_response = 0, 555 | }; 556 | struct mei_header mei = { 557 | .is_complete = 1, 558 | .length = sizeof(mkhi) + sizeof(memory), 559 | .host_address = MEI_HOST_ADDRESS, 560 | .client_address = MEI_ADDRESS_MKHI, 561 | }; 562 | 563 | printf("ME: Debug memory to 0x%zx ...", (size_t)physaddr); 564 | if (mei_sendrecv(&mei, &mkhi, &memory, &data, 0) < 0) { 565 | printf("failed\n"); 566 | return -1; 567 | } else { 568 | printf("done\n"); 569 | } 570 | return 0; 571 | } 572 | 573 | /* Prepare ME for MEI messages */ 574 | uint32_t intel_mei_setup(struct pci_dev *dev) 575 | { 576 | struct mei_csr host; 577 | uint32_t reg32; 578 | uint32_t pagerounded; 579 | 580 | mei_base_address = dev->base_addr[0] & ~0xf; 581 | pagerounded = mei_base_address & ~0xfff; 582 | mei_mmap = map_physical(pagerounded, 0x2000) + mei_base_address - pagerounded; 583 | 584 | /* Ensure Memory and Bus Master bits are set */ 585 | reg32 = pci_read_long(dev, PCI_COMMAND); 586 | reg32 |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; 587 | pci_write_long(dev, PCI_COMMAND, reg32); 588 | 589 | /* Clean up status for next message */ 590 | read_host_csr(&host); 591 | host.interrupt_generate = 1; 592 | host.ready = 1; 593 | host.reset = 0; 594 | write_host_csr(&host); 595 | 596 | return 0; 597 | } 598 | 599 | void intel_mei_unmap(void) 600 | { 601 | //munmap(mei_mmap, 0x2000); 602 | } 603 | 604 | /* Read the Extend register hash of ME firmware */ 605 | int intel_me_extend_valid(struct pci_dev *dev) 606 | { 607 | struct me_heres status; 608 | uint32_t extend[8] = {0}; 609 | int i, count = 0; 610 | 611 | pci_read_dword_ptr(dev, &status, PCI_ME_HERES); 612 | if (!status.extend_feature_present) { 613 | printf("ME: Extend Feature not present\n"); 614 | return -1; 615 | } 616 | 617 | if (!status.extend_reg_valid) { 618 | printf("ME: Extend Register not valid\n"); 619 | return -1; 620 | } 621 | 622 | switch (status.extend_reg_algorithm) { 623 | case PCI_ME_EXT_SHA1: 624 | count = 5; 625 | printf("ME: Extend SHA-1: "); 626 | break; 627 | case PCI_ME_EXT_SHA256: 628 | count = 8; 629 | printf("ME: Extend SHA-256: "); 630 | break; 631 | default: 632 | printf("ME: Extend Algorithm %d unknown\n", 633 | status.extend_reg_algorithm); 634 | return -1; 635 | } 636 | 637 | for (i = 0; i < count; ++i) { 638 | extend[i] = pci_read_long(dev, PCI_ME_HER(i)); 639 | printf("%08x", extend[i]); 640 | } 641 | printf("\n"); 642 | 643 | return 0; 644 | } 645 | -------------------------------------------------------------------------------- /me.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the coreboot project. 3 | * 4 | * Copyright (C) 2011 The Chromium OS Authors. All rights reserved. 5 | * Copyright (C) 2013 Damien Zammit 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License as 9 | * published by the Free Software Foundation; version 2 of 10 | * the License. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, 20 | * MA 02110-1301 USA 21 | */ 22 | 23 | #ifndef ME_H 24 | #define ME_H 25 | 26 | #include 27 | #include 28 | 29 | #define ME_RETRY 100000 /* 1 second */ 30 | #define ME_DELAY 10 /* 10 us */ 31 | 32 | #pragma pack(1) 33 | 34 | /* 35 | * Management Engine PCI registers 36 | */ 37 | 38 | #define PCI_ME_HFS 0x40 39 | #define ME_HFS_CWS_RESET 0 40 | #define ME_HFS_CWS_INIT 1 41 | #define ME_HFS_CWS_REC 2 42 | #define ME_HFS_CWS_NORMAL 5 43 | #define ME_HFS_CWS_WAIT 6 44 | #define ME_HFS_CWS_TRANS 7 45 | #define ME_HFS_CWS_INVALID 8 46 | #define ME_HFS_STATE_PREBOOT 0 47 | #define ME_HFS_STATE_M0_UMA 1 48 | #define ME_HFS_STATE_M3 4 49 | #define ME_HFS_STATE_M0 5 50 | #define ME_HFS_STATE_BRINGUP 6 51 | #define ME_HFS_STATE_ERROR 7 52 | #define ME_HFS_ERROR_NONE 0 53 | #define ME_HFS_ERROR_UNCAT 1 54 | #define ME_HFS_ERROR_IMAGE 3 55 | #define ME_HFS_ERROR_DEBUG 4 56 | #define ME_HFS_MODE_NORMAL 0 57 | #define ME_HFS_MODE_DEBUG 2 58 | #define ME_HFS_MODE_DIS 3 59 | #define ME_HFS_MODE_OVER_JMPR 4 60 | #define ME_HFS_MODE_OVER_MEI 5 61 | #define ME_HFS_BIOS_DRAM_ACK 1 62 | #define ME_HFS_ACK_NO_DID 0 63 | #define ME_HFS_ACK_RESET 1 64 | #define ME_HFS_ACK_PWR_CYCLE 2 65 | #define ME_HFS_ACK_S3 3 66 | #define ME_HFS_ACK_S4 4 67 | #define ME_HFS_ACK_S5 5 68 | #define ME_HFS_ACK_GBL_RESET 6 69 | #define ME_HFS_ACK_CONTINUE 7 70 | 71 | struct me_hfs { 72 | uint32_t working_state: 4; 73 | uint32_t mfg_mode: 1; 74 | uint32_t fpt_bad: 1; 75 | uint32_t operation_state: 3; 76 | uint32_t fw_init_complete: 1; 77 | uint32_t ft_bup_ld_flr: 1; 78 | uint32_t update_in_progress: 1; 79 | uint32_t error_code: 4; 80 | uint32_t operation_mode: 4; 81 | uint32_t reserved: 4; 82 | uint32_t boot_options_present: 1; 83 | uint32_t ack_data: 3; 84 | uint32_t bios_msg_ack: 4; 85 | } __attribute__ ((packed)); 86 | 87 | #define PCI_ME_UMA 0x44 88 | 89 | struct me_uma { 90 | uint32_t size: 6; 91 | uint32_t reserved_1: 10; 92 | uint32_t valid: 1; 93 | uint32_t reserved_0: 14; 94 | uint32_t set_to_one: 1; 95 | } __attribute__ ((packed)); 96 | 97 | #define PCI_ME_H_GS 0x4c 98 | #define ME_INIT_DONE 1 99 | #define ME_INIT_STATUS_SUCCESS 0 100 | #define ME_INIT_STATUS_NOMEM 1 101 | #define ME_INIT_STATUS_ERROR 2 102 | 103 | struct me_did { 104 | uint32_t uma_base: 16; 105 | uint32_t reserved: 8; 106 | uint32_t status: 4; 107 | uint32_t init_done: 4; 108 | } __attribute__ ((packed)); 109 | 110 | #define PCI_ME_GMES 0x48 111 | #define ME_GMES_PHASE_ROM 0 112 | #define ME_GMES_PHASE_BUP 1 113 | #define ME_GMES_PHASE_UKERNEL 2 114 | #define ME_GMES_PHASE_POLICY 3 115 | #define ME_GMES_PHASE_MODULE 4 116 | #define ME_GMES_PHASE_UNKNOWN 5 117 | #define ME_GMES_PHASE_HOST 6 118 | 119 | struct me_gmes { 120 | uint32_t bist_in_prog : 1; 121 | uint32_t icc_prog_sts : 2; 122 | uint32_t invoke_mebx : 1; 123 | uint32_t cpu_replaced_sts : 1; 124 | uint32_t mbp_rdy : 1; 125 | uint32_t mfs_failure : 1; 126 | uint32_t warm_rst_req_for_df : 1; 127 | uint32_t cpu_replaced_valid : 1; 128 | uint32_t reserved_1 : 2; 129 | uint32_t fw_upd_ipu : 1; 130 | uint32_t reserved_2 : 4; 131 | uint32_t current_state: 8; 132 | uint32_t current_pmevent: 4; 133 | uint32_t progress_code: 4; 134 | } __attribute__ ((packed)); 135 | 136 | #define PCI_ME_HERES 0xbc 137 | #define PCI_ME_EXT_SHA1 0x00 138 | #define PCI_ME_EXT_SHA256 0x02 139 | #define PCI_ME_HER(x) (0xc0+(4*(x))) 140 | 141 | struct me_heres { 142 | uint32_t extend_reg_algorithm: 4; 143 | uint32_t reserved: 26; 144 | uint32_t extend_feature_present: 1; 145 | uint32_t extend_reg_valid: 1; 146 | } __attribute__ ((packed)); 147 | 148 | struct me_thermal_reporting { 149 | uint32_t polling_timeout: 8; 150 | uint32_t smbus_ec_msglen: 8; 151 | uint32_t smbus_ec_msgpec: 8; 152 | uint32_t dimmnumber: 8; 153 | } __attribute__ ((packed)); 154 | 155 | /* 156 | * Management Engine MEI registers 157 | */ 158 | 159 | #define MEI_H_CB_WW 0x00 160 | #define MEI_H_CSR 0x04 161 | #define MEI_ME_CB_RW 0x08 162 | #define MEI_ME_CSR_HA 0x0c 163 | 164 | struct mei_csr { 165 | uint32_t interrupt_enable: 1; 166 | uint32_t interrupt_status: 1; 167 | uint32_t interrupt_generate: 1; 168 | uint32_t ready: 1; 169 | uint32_t reset: 1; 170 | uint32_t reserved: 3; 171 | uint32_t buffer_read_ptr: 8; 172 | uint32_t buffer_write_ptr: 8; 173 | uint32_t buffer_depth: 8; 174 | } __attribute__ ((packed)); 175 | 176 | #define MEI_ADDRESS_HBM 0x00 177 | #define MEI_ADDRESS_CORE_WD 0x01 178 | #define MEI_ADDRESS_AMT 0x02 179 | #define MEI_ADDRESS_RESERVED 0x03 180 | #define MEI_ADDRESS_WDT 0x04 181 | #define MEI_ADDRESS_POLICY 0x05 182 | #define MEI_ADDRESS_PASSWORD 0x06 183 | #define MEI_ADDRESS_MKHI 0x07 184 | #define MEI_ADDRESS_ICC 0x08 185 | #define MEI_ADDRESS_THERMAL 0x09 186 | #define MEI_ADDRESS_SPI 0x0a 187 | 188 | #define MEI_HOST_ADDRESS 0 189 | 190 | struct mei_header { 191 | uint32_t client_address: 8; 192 | uint32_t host_address: 8; 193 | uint32_t length: 9; 194 | uint32_t reserved: 6; 195 | uint32_t is_complete: 1; 196 | } __attribute__ ((packed)); 197 | 198 | #define MKHI_GROUP_ID_CBM 0x00 199 | #define MKHI_GROUP_ID_PM 0x01 200 | #define MKHI_GROUP_ID_PWD 0x02 201 | #define MKHI_GROUP_ID_FWCAPS 0x03 202 | #define MKHI_GROUP_ID_APP 0x04 203 | #define MKHI_GROUP_ID_SPI 0x05 204 | #define MKHI_GROUP_ID_MDES 0x08 205 | #define MKHI_GROUP_ID_MAX 0x09 206 | #define MKHI_GROUP_ID_GEN 0xff 207 | 208 | #define MKHI_FWCAPS_GET_RULE 0x02 209 | #define MKHI_FWCAPS_SET_RULE 0x03 210 | #define MKHI_GLOBAL_RESET 0x0b 211 | 212 | #define GEN_GET_MKHI_VERSION 0x01 213 | #define GEN_GET_FW_VERSION 0x02 214 | #define GEN_UNCONFIG_NO_PWD 0x0d 215 | #define GEN_SET_DEBUG_MEM 0x11 216 | 217 | #define FWCAPS_ME_FWU_RULE 0x2e 218 | #define FWCAPS_OVERRIDE 0x14 219 | 220 | #define MKHI_THERMAL_REPORTING 0x00 221 | #define MKHI_GET_FW_VERSION 0x02 222 | #define MKHI_MDES_ENABLE 0x09 223 | #define MKHI_END_OF_POST 0x0c 224 | #define MKHI_FEATURE_OVERRIDE 0x14 225 | 226 | #define HBM_HOST_START_REQ_CMD 0x01 227 | #define HBM_HOST_STOP_REQ_CMD 0x02 228 | #define HBM_ME_STOP_REQ_CMD 0x03 229 | #define HBM_HOST_ENUM_REQ_CMD 0x04 230 | #define HBM_HOST_CLIENT_PROPERTIES_REQ_CMD 0x05 231 | #define HBM_CLIENT_CONNECT_REQ_CMD 0x06 232 | #define HBM_CLIENT_DISCONNECT_REQ_CMD 0x07 233 | 234 | struct mkhi_header { 235 | uint32_t group_id: 8; 236 | uint32_t command: 7; 237 | uint32_t is_response: 1; 238 | uint32_t reserved: 8; 239 | uint32_t result: 8; 240 | } __attribute__ ((packed)); 241 | 242 | struct me_fw_version { 243 | uint16_t code_minor; 244 | uint16_t code_major; 245 | uint16_t code_build_number; 246 | uint16_t code_hot_fix; 247 | uint16_t recovery_minor; 248 | uint16_t recovery_major; 249 | uint16_t recovery_build_number; 250 | uint16_t recovery_hot_fix; 251 | uint16_t fitcminor; 252 | uint16_t fitcmajor; 253 | uint16_t fitcbuildno; 254 | uint16_t fitchotfix; 255 | } __attribute__ ((packed)); 256 | 257 | 258 | #define HECI_EOP_STATUS_SUCCESS 0x0 259 | #define HECI_EOP_PERFORM_GLOBAL_RESET 0x1 260 | 261 | #define CBM_RR_GLOBAL_RESET 0x01 262 | 263 | #define GLOBAL_RESET_BIOS_MRC 0x01 264 | #define GLOBAL_RESET_BIOS_POST 0x02 265 | #define GLOBAL_RESET_MEBX 0x03 266 | 267 | struct me_global_reset { 268 | uint8_t request_origin; 269 | uint8_t reset_type; 270 | } __attribute__ ((packed)); 271 | 272 | typedef enum { 273 | ME_NORMAL_BIOS_PATH, 274 | ME_S3WAKE_BIOS_PATH, 275 | ME_ERROR_BIOS_PATH, 276 | ME_RECOVERY_BIOS_PATH, 277 | ME_DISABLE_BIOS_PATH, 278 | ME_FIRMWARE_UPDATE_BIOS_PATH, 279 | } me_bios_path; 280 | 281 | typedef struct { 282 | uint32_t major_version : 16; 283 | uint32_t minor_version : 16; 284 | uint32_t hotfix_version : 16; 285 | uint32_t build_version : 16; 286 | } __attribute__ ((packed)) mbp_fw_version_name; 287 | 288 | typedef struct { 289 | uint8_t num_icc_profiles; 290 | uint8_t icc_profile_soft_strap; 291 | uint8_t icc_profile_index; 292 | uint8_t reserved; 293 | uint32_t register_lock_mask[3]; 294 | } __attribute__ ((packed)) mbp_icc_profile; 295 | 296 | typedef struct { 297 | uint32_t full_net : 1; 298 | uint32_t std_net : 1; 299 | uint32_t manageability : 1; 300 | uint32_t small_business : 1; 301 | uint32_t l3manageability : 1; 302 | uint32_t intel_at : 1; 303 | uint32_t intel_cls : 1; 304 | uint32_t reserved : 3; 305 | uint32_t intel_mpc : 1; 306 | uint32_t icc_over_clocking : 1; 307 | uint32_t pavp : 1; 308 | uint32_t reserved_1 : 4; 309 | uint32_t ipv6 : 1; 310 | uint32_t kvm : 1; 311 | uint32_t och : 1; 312 | uint32_t vlan : 1; 313 | uint32_t tls : 1; 314 | uint32_t reserved_4 : 1; 315 | uint32_t wlan : 1; 316 | uint32_t reserved_5 : 8; 317 | } __attribute__ ((packed)) mefwcaps_sku; 318 | 319 | typedef struct { 320 | uint16_t lock_state : 1; 321 | uint16_t authenticate_module : 1; 322 | uint16_t s3authentication : 1; 323 | uint16_t flash_wear_out : 1; 324 | uint16_t flash_variable_security : 1; 325 | uint16_t wwan3gpresent : 1; 326 | uint16_t wwan3goob : 1; 327 | uint16_t reserved : 9; 328 | } __attribute__ ((packed)) tdt_state_flag; 329 | 330 | typedef struct { 331 | uint8_t state; 332 | uint8_t last_theft_trigger; 333 | tdt_state_flag flags; 334 | } __attribute__ ((packed)) tdt_state_info; 335 | 336 | typedef struct { 337 | uint32_t platform_target_usage_type : 4; 338 | uint32_t platform_target_market_type : 2; 339 | uint32_t super_sku : 1; 340 | uint32_t reserved : 1; 341 | uint32_t intel_me_fw_image_type : 4; 342 | uint32_t platform_brand : 4; 343 | uint32_t reserved_1 : 16; 344 | } __attribute__ ((packed)) platform_type_rule_data; 345 | 346 | typedef struct { 347 | mefwcaps_sku fw_capabilities; 348 | uint8_t available; 349 | } mbp_fw_caps; 350 | 351 | typedef struct { 352 | uint16_t device_id; 353 | uint16_t fuse_test_flags; 354 | uint32_t umchid[4]; 355 | } __attribute__ ((packed)) mbp_rom_bist_data; 356 | 357 | typedef struct { 358 | uint32_t key[8]; 359 | } mbp_platform_key; 360 | 361 | typedef struct { 362 | platform_type_rule_data rule_data; 363 | uint8_t available; 364 | } mbp_plat_type; 365 | 366 | typedef struct { 367 | mbp_fw_version_name fw_version_name; 368 | mbp_fw_caps fw_caps_sku; 369 | mbp_rom_bist_data rom_bist_data; 370 | mbp_platform_key platform_key; 371 | mbp_plat_type fw_plat_type; 372 | mbp_icc_profile icc_profile; 373 | tdt_state_info at_state; 374 | uint32_t mfsintegrity; 375 | } me_bios_payload; 376 | 377 | typedef struct { 378 | uint32_t mbp_size : 8; 379 | uint32_t num_entries : 8; 380 | uint32_t rsvd : 16; 381 | } __attribute__ ((packed)) mbp_header; 382 | 383 | typedef struct { 384 | uint32_t app_id : 8; 385 | uint32_t item_id : 8; 386 | uint32_t length : 8; 387 | uint32_t rsvd : 8; 388 | } __attribute__ ((packed)) mbp_item_header; 389 | 390 | struct me_fwcaps { 391 | uint32_t id; 392 | uint8_t length; 393 | mefwcaps_sku caps_sku; 394 | uint8_t reserved[3]; 395 | } __attribute__ ((packed)); 396 | 397 | struct me_debug_mem { 398 | uint32_t debug_phys; 399 | uint32_t debug_size; 400 | uint32_t me_phys; 401 | uint32_t me_size; 402 | } __attribute__ ((packed)); 403 | 404 | void intel_me_status(uint32_t hfs, uint32_t gmes); 405 | void mkhi_thermal(void); 406 | uint32_t intel_mei_setup(struct pci_dev *dev); 407 | void intel_mei_unmap(void); 408 | int mkhi_get_fwcaps(void); 409 | int mkhi_get_fw_version(void); 410 | int mkhi_debug_me_memory(void *addr); 411 | void mei_reset(void); 412 | void udelay(uint32_t usecs); 413 | int intel_me_extend_valid(struct pci_dev *dev); 414 | 415 | #endif 416 | -------------------------------------------------------------------------------- /me_status.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the coreboot project. 3 | * 4 | * Copyright (C) 2011 The Chromium OS Authors. All rights reserved. 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public License as 8 | * published by the Free Software Foundation; version 2 of 9 | * the License. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, 19 | * MA 02110-1301 USA 20 | */ 21 | 22 | #include 23 | #include "me.h" 24 | 25 | #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 26 | 27 | /* HFS1[3:0] Current Working State Values */ 28 | static const char *me_cws_values[] = { 29 | [ME_HFS_CWS_RESET] = "Reset", 30 | [ME_HFS_CWS_INIT] = "Initializing", 31 | [ME_HFS_CWS_REC] = "Recovery", 32 | [ME_HFS_CWS_NORMAL] = "Normal", 33 | [ME_HFS_CWS_WAIT] = "Platform Disable Wait", 34 | [ME_HFS_CWS_TRANS] = "OP State Transition", 35 | [ME_HFS_CWS_INVALID] = "Invalid CPU Plugged In" 36 | }; 37 | 38 | /* HFS1[8:6] Current Operation State Values */ 39 | static const char *me_opstate_values[] = { 40 | [ME_HFS_STATE_PREBOOT] = "Preboot", 41 | [ME_HFS_STATE_M0_UMA] = "M0 with UMA", 42 | [ME_HFS_STATE_M3] = "M3 without UMA", 43 | [ME_HFS_STATE_M0] = "M0 without UMA", 44 | [ME_HFS_STATE_BRINGUP] = "Bring up", 45 | [ME_HFS_STATE_ERROR] = "M0 without UMA but with error" 46 | }; 47 | 48 | /* HFS[19:16] Current Operation Mode Values */ 49 | static const char *me_opmode_values[] = { 50 | [ME_HFS_MODE_NORMAL] = "Normal", 51 | [ME_HFS_MODE_DEBUG] = "Debug", 52 | [ME_HFS_MODE_DIS] = "Soft Temporary Disable", 53 | [ME_HFS_MODE_OVER_JMPR] = "Security Override via Jumper", 54 | [ME_HFS_MODE_OVER_MEI] = "Security Override via MEI Message" 55 | }; 56 | 57 | /* HFS[15:12] Error Code Values */ 58 | static const char *me_error_values[] = { 59 | [ME_HFS_ERROR_NONE] = "No Error", 60 | [ME_HFS_ERROR_UNCAT] = "Uncategorized Failure", 61 | [ME_HFS_ERROR_IMAGE] = "Image Failure", 62 | [ME_HFS_ERROR_DEBUG] = "Debug Failure" 63 | }; 64 | 65 | /* GMES[31:28] ME Progress Code */ 66 | static const char *me_progress_values[] = { 67 | [ME_GMES_PHASE_ROM] = "ROM Phase", 68 | [ME_GMES_PHASE_BUP] = "BUP Phase", 69 | [ME_GMES_PHASE_UKERNEL] = "uKernel Phase", 70 | [ME_GMES_PHASE_POLICY] = "Policy Module", 71 | [ME_GMES_PHASE_MODULE] = "Module Loading", 72 | [ME_GMES_PHASE_UNKNOWN] = "Unknown", 73 | [ME_GMES_PHASE_HOST] = "Host Communication" 74 | }; 75 | 76 | /* GMES[27:24] Power Management Event */ 77 | static const char *me_pmevent_values[] = { 78 | [0x00] = "Clean Moff->Mx wake", 79 | [0x01] = "Moff->Mx wake after an error", 80 | [0x02] = "Clean global reset", 81 | [0x03] = "Global reset after an error", 82 | [0x04] = "Clean Intel ME reset", 83 | [0x05] = "Intel ME reset due to exception", 84 | [0x06] = "Pseudo-global reset", 85 | [0x07] = "S0/M0->Sx/M3", 86 | [0x08] = "Sx/M3->S0/M0", 87 | [0x09] = "Non-power cycle reset", 88 | [0x0a] = "Power cycle reset through M3", 89 | [0x0b] = "Power cycle reset through Moff", 90 | [0x0c] = "Sx/Mx->Sx/Moff" 91 | }; 92 | 93 | /* Progress Code 0 states */ 94 | static const char *me_progress_rom_values[] = { 95 | [0x00] = "BEGIN", 96 | [0x06] = "DISABLE" 97 | }; 98 | 99 | /* Progress Code 1 states */ 100 | static const char *me_progress_bup_values[] = { 101 | [0x00] = "Initialization starts", 102 | [0x01] = "Disable the host wake event", 103 | [0x04] = "Flow determination start process", 104 | [0x08] = "Error reading/matching the VSCC table in the descriptor", 105 | [0x0a] = "Check to see if straps say ME DISABLED", 106 | [0x0b] = "Timeout waiting for PWROK", 107 | [0x0d] = "Possibly handle BUP manufacturing override strap", 108 | [0x11] = "Bringup in M3", 109 | [0x12] = "Bringup in M0", 110 | [0x13] = "Flow detection error", 111 | [0x15] = "M3 clock switching error", 112 | [0x18] = "M3 kernel load", 113 | [0x1c] = "T34 missing - cannot program ICC", 114 | [0x1f] = "Waiting for DID BIOS message", 115 | [0x20] = "Waiting for DID BIOS message failure", 116 | [0x21] = "DID reported an error", 117 | [0x22] = "Enabling UMA", 118 | [0x23] = "Enabling UMA error", 119 | [0x24] = "Sending DID Ack to BIOS", 120 | [0x25] = "Sending DID Ack to BIOS error", 121 | [0x26] = "Switching clocks in M0", 122 | [0x27] = "Switching clocks in M0 error", 123 | [0x28] = "ME in temp disable", 124 | [0x32] = "M0 kernel load", 125 | }; 126 | 127 | /* Progress Code 3 states */ 128 | static const char *me_progress_policy_values[] = { 129 | [0x00] = "Entery into Policy Module", 130 | [0x03] = "Received S3 entry", 131 | [0x04] = "Received S4 entry", 132 | [0x05] = "Received S5 entry", 133 | [0x06] = "Received UPD entry", 134 | [0x07] = "Received PCR entry", 135 | [0x08] = "Received NPCR entry", 136 | [0x09] = "Received host wake", 137 | [0x0a] = "Received AC<>DC switch", 138 | [0x0b] = "Received DRAM Init Done", 139 | [0x0c] = "VSCC Data not found for flash device", 140 | [0x0d] = "VSCC Table is not valid", 141 | [0x0e] = "Flash Partition Boundary is outside address space", 142 | [0x0f] = "ME cannot access the chipset descriptor region", 143 | [0x10] = "Required VSCC values for flash parts do not match", 144 | }; 145 | 146 | void intel_me_status(uint32_t hfs, uint32_t gmes) 147 | { 148 | /* Check Current States */ 149 | printf("ME: FW Partition Table : %s\n", 150 | ((hfs & 0x20) >> 5) ? "BAD" : "OK"); 151 | printf("ME: Bringup Loader Failure : %s\n", 152 | ((hfs & 0x400) >> 10) ? "YES" : "NO"); 153 | printf("ME: Firmware Init Complete : %s\n", 154 | ((hfs & 0x200) >> 9) ? "YES" : "NO"); 155 | printf("ME: Manufacturing Mode : %s\n", 156 | ((hfs & 0x10) >> 4) ? "YES" : "NO"); 157 | printf("ME: Boot Options Present : %s\n", 158 | ((hfs & 0x1000000) >> 24) ? "YES" : "NO"); 159 | printf("ME: Update In Progress : %s\n", 160 | ((hfs & 0x800) >> 11) ? "YES" : "NO"); 161 | printf("ME: Current Working State : %s\n", 162 | me_cws_values[hfs & 0xf]); 163 | printf("ME: Current Operation State : %s\n", 164 | me_opstate_values[(hfs & 0x1c0) >> 6]); 165 | printf("ME: Current Operation Mode : %s\n", 166 | me_opmode_values[(hfs & 0xf0000) >> 16]); 167 | printf("ME: Error Code : %s\n", 168 | me_error_values[(hfs & 0xf000) >> 12]); 169 | printf("ME: Progress Phase : %s\n", 170 | me_progress_values[(gmes & 0xf0000000) >> 28]); 171 | printf("ME: Power Management Event : %s\n", 172 | me_pmevent_values[(gmes & 0xf000000) >> 24]); 173 | 174 | printf("ME: Progress Phase State : "); 175 | switch ((gmes & 0xf0000000) >> 28) { 176 | case ME_GMES_PHASE_ROM: /* ROM Phase */ 177 | printf("%s", 178 | me_progress_rom_values[(gmes & 0xff0000) >> 16]); 179 | break; 180 | 181 | case ME_GMES_PHASE_BUP: /* Bringup Phase */ 182 | if ((gmes & 0xff0000) >> 16 < ARRAY_SIZE(me_progress_bup_values) 183 | && me_progress_bup_values[(gmes & 0xff0000) >> 16]) 184 | printf("%s", 185 | me_progress_bup_values[(gmes & 0xff0000) >> 16]); 186 | else 187 | printf("0x%02x", (gmes & 0xff0000) >> 16); 188 | break; 189 | 190 | case ME_GMES_PHASE_POLICY: /* Policy Module Phase */ 191 | if ((gmes & 0xff0000) >> 16 < ARRAY_SIZE(me_progress_policy_values) 192 | && me_progress_policy_values[(gmes & 0xff0000) >> 16]) 193 | printf("%s", 194 | me_progress_policy_values[(gmes & 0xff0000) >> 16]); 195 | else 196 | printf("0x%02x", (gmes & 0xff0000) >> 16); 197 | break; 198 | 199 | case ME_GMES_PHASE_HOST: /* Host Communication Phase */ 200 | if (!((gmes & 0xff0000) >> 16)) 201 | printf("Host communication established"); 202 | else 203 | printf("0x%02x", (gmes & 0xff0000) >> 16); 204 | break; 205 | 206 | default: 207 | printf("Unknown 0x%02x", (gmes & 0xff0000) >> 16); 208 | } 209 | printf("\n"); 210 | } 211 | -------------------------------------------------------------------------------- /mmap.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Damien Zammit 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License as 6 | * published by the Free Software Foundation; either version 2 of 7 | * the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | #include "mmap.h" 16 | #include 17 | 18 | int fd_mem; 19 | 20 | void *map_physical_exact(uint64_t phys_addr, uint64_t mapto, size_t len) 21 | { 22 | void *virt_addr; 23 | int err; 24 | 25 | virt_addr = mmap((void*)mapto, len, PROT_WRITE | PROT_READ, MAP_SHARED|MAP_FIXED, 26 | fd_mem, (off_t) phys_addr); 27 | 28 | if (virt_addr == MAP_FAILED) { 29 | err = errno; 30 | printf("Error mapping physical memory 0x%016" PRIx64 "[0x%zx] ERRNO=%d\n", 31 | phys_addr, len, err); 32 | return NULL; 33 | } 34 | 35 | return virt_addr; 36 | } 37 | 38 | void *map_physical(uint64_t phys_addr, size_t len) 39 | { 40 | void *virt_addr; 41 | int err; 42 | 43 | virt_addr = mmap(NULL, len, PROT_WRITE | PROT_READ, MAP_SHARED, 44 | fd_mem, (off_t) phys_addr); 45 | 46 | if (virt_addr == MAP_FAILED) { 47 | err = errno; 48 | printf("Error mapping physical memory 0x%016" PRIx64 "[0x%zx] ERRNO=%d\n", 49 | phys_addr, len, err); 50 | return NULL; 51 | } 52 | 53 | return virt_addr; 54 | } 55 | 56 | void unmap_physical(void *virt_addr, size_t len) 57 | { 58 | munmap(virt_addr, len); 59 | } 60 | -------------------------------------------------------------------------------- /mmap.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Damien Zammit 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License as 6 | * published by the Free Software Foundation; either version 2 of 7 | * the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | extern int fd_mem; 22 | void *map_physical(uint64_t phys_addr, size_t len); 23 | void unmap_physical(void *virt_addr, size_t len); 24 | --------------------------------------------------------------------------------