nvramtool: 64bit safe CBFS handling
[coreboot.git] / util / getpir / getpir.c
1 /* getpir.c : This software is released under GPL
2  * For coreboot use only
3  * Aug 26 2001 , Nikolai Vladychevski, <niko@isl.net.mx>
4  * 2007.04.09 Jeremy Jackson <jerj@coplanar.net>
5  *     updated for amd64 and general 64 bit portability
6  * 2010.04.24 Marc Bertens <mbertens@xs4all.nl>
7  *     Added functionality to read a image file for checking the checksum of the PIR
8  */
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <unistd.h>
14 #include <fcntl.h>
15 #include <sys/mman.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18
19 #include "pirq_routing.h"
20 #include "checksum.h"
21 #include "code_gen.h"
22
23 #if defined (__sun) && (defined(__i386) || defined(__amd64))
24 #  define MEM_DEV "/dev/xsvc"
25 #else
26 #  define MEM_DEV "/dev/mem"
27 #endif
28
29 /**
30  *      The probe_table() is now called with the pointer to the memory,
31  *      this is to handle both the assessing memory and a file.
32  *
33  *      This function now dumps the table found to the stdout, with
34  *      descriptions, it is special handy when building a PIRQ table
35  *      for a board to check the checksum.
36  */
37 static struct irq_routing_table *probe_table(char* ptr)
38 {
39         /**
40          * Signature to search for $PIR<2-byte-version>
41          *
42          *      this is to be sure that we find the correct table.
43          */
44         char signature[] = "$PIR\x00\x01";
45         /** cast the pointer */
46         struct irq_routing_table *rt = (struct irq_routing_table *)ptr;
47         int size = 16;
48         int checksum_result;
49         do {
50                 /** find the PIRQ table */
51                 rt = (struct irq_routing_table *) memmem(ptr + size, 16, signature, 6);
52                 if (rt != NULL) {
53                         /** found the table */
54                         int i, ts = (rt->size - 32) / 16;
55                         struct irq_info *se_arr;
56                         se_arr = (struct irq_info *) ((char *) rt + 32);
57                         /** Dump the table information to the stdout */
58                         printf("Found PCI IRQ routing table signature at %p.\n", (void *) ((char *) rt - ptr + 0xf0000));
59                         printf("SIGNATURE            = %s\n", (char*)&rt->signature);
60                         printf("VERSION              = %04x\n", rt->version);
61                         printf("SIZE                 = %i\n", rt->size);
62                         printf("MAX_DEVICES_ON_BUS   = 32 + 16 * %d\n", ts);
63                         printf("INT_ROUTER_BUS       = 0x%02x\n", rt->rtr_bus);
64                         printf("INT_ROUTER DEVICE    = (0x%02x << 3) | 0x%01x\n", rt->rtr_devfn >> 3, rt->rtr_devfn & 7);
65                         printf("IRQ_DEVOTED_TO_PCI   = %#x\n", rt->exclusive_irqs);
66                         printf("VENDOR               = %#x\n", rt->rtr_vendor);
67                         printf("DEVICE               = %#x\n", rt->rtr_device);
68                         printf("MINIPORT             = %#x\n", rt->miniport_data);
69                         printf("CHECKSUM             = %#x\n", rt->checksum);
70                         printf("\tbus , dev        | fn,   {link, bitmap}, {link, bitmap}, {link, bitmap}, {link, bitmap}, slot, rfu\n");
71                         for (i = 0; i < ts; i++) {
72                                 printf("\t0x%02x, (0x%02x << 3) | 0x%01x, {{0x%02x, 0x%04x}, {0x%02x, 0x%04x}, {0x%02x, 0x%04x}, {0x%02x, 0x%04x}}, 0x%x, 0x%x},\n",
73                                         (se_arr+i)->bus,                        (se_arr+i)->devfn >> 3,
74                                         (se_arr+i)->devfn & 7,          (se_arr+i)->irq[0].link,
75                                         (se_arr+i)->irq[0].bitmap,      (se_arr+i)->irq[1].link,
76                                         (se_arr+i)->irq[1].bitmap,      (se_arr+i)->irq[2].link,
77                                         (se_arr+i)->irq[2].bitmap,      (se_arr+i)->irq[3].link,
78                                         (se_arr+i)->irq[3].bitmap,      (se_arr+i)->slot,
79                                         (se_arr+i)->rfu);
80                         }
81                         /** A table should not be over 0x400 bytes */
82                         if (rt->size > 0x400) {
83                                 return NULL;
84                         }
85                         printf("Validating...\n");
86                         /** Calculate the checksum value */
87                         checksum_result = calc_checksum(rt);
88                         /** Show the calculatedchecksum value */
89                         printf("CHECKSUM             = %#x\n", 0x100-((checksum_result - rt->checksum) & 0xFF));
90                         /** and the result of the calculation */
91                         if (!checksum_result) {
92                                 printf("checksum is ok.\n");
93                                 break;
94                         } else {
95                                 printf("checksum is wrong.\n");
96                         }
97                 }
98                 size += 16;
99         } while (size < 0xFFFF);
100         if (size >= 0xFFFF) {
101                 /** When the functions comes here there is no PIRQ table found. */
102                 printf("No PCI IRQ routing table signature found.\n");
103                 return NULL;
104         }
105
106         return rt;
107 }
108
109 int main(int argc, char* argv[])
110 {
111         char* ptr;
112         int fd_mem = -1;
113         struct irq_routing_table* rt = NULL;
114         void* bios_image = NULL;
115         if ( argc > 1 )
116         {
117                 /** there a paramater passed to the program, assume that it is a menory file */
118                 printf("Opening memory image file '%s'\n", argv[1]);
119                 /** Open the file */
120                 fd_mem = open(argv[1], O_RDONLY);
121                 if (fd_mem > 0) {
122                         /** get tyhe size of the file */
123                         int file_size = lseek(fd_mem, 0, SEEK_END);
124                         printf("Memory image '%i'\n", file_size);
125                         /** get a memory block for it. */
126                         bios_image = malloc(file_size);
127                         if (bios_image) {
128                                 /** Fill the created buffer */
129                                 lseek(fd_mem, 0, SEEK_SET);
130                                 read(fd_mem, bios_image, file_size);
131                                 /** set the pointer for the probe function */
132                                 ptr = (char*)bios_image;
133                         } else {
134                                 /* no memory available ? */
135                                 perror("Failed to open imagefile\n");
136                                 return (-3);
137                         }
138                 } else {
139                         /** An error occourd, just exit with a message */
140                         perror("Failed to open imagefile");
141                         return (-2);
142                 }
143         } else {
144                 /** No paramaters means that the program will access the system memory */
145                 printf("Accessing memory\n");
146                 if (getuid()) {
147                         /** i'm not root message !!!! */
148                         fprintf(stderr, "Run me as root, I need access to " MEM_DEV ".\n");
149                 }
150                 /** open the system memory */
151                 fd_mem = open(MEM_DEV, O_RDONLY);
152                 if (fd_mem < 0) {
153                         /** could not open the system memory, exit with a message */
154                         perror("Could not open " MEM_DEV ":");
155                         exit(1);
156                 }
157                 printf("Probing PIRQ table in memory.\n");
158                 ptr = mmap(0, 0x10000, PROT_READ, MAP_SHARED, fd_mem, (off_t)0xf0000);
159                 if (ptr == MAP_FAILED) {
160                         /** could not map the system memory, exit with a message */
161                         perror("Mapping system memory failed: ");
162                         close(fd_mem);
163                         return (1);
164                 }
165         }
166         if (ptr) {
167                 /** now do the actual probe function */
168                 rt = probe_table(ptr);
169                 if (rt != NULL && bios_image == NULL) {
170                         /** when probing system memory we write the 'irq_tables.c' code file */
171                         printf("Creating irq_tables.c ...\n");
172                         code_gen("irq_tables.c", rt);
173                         printf("Done, you can move the file to the coreboot tree now.\n");
174                 }
175         } else {
176                 printf("invalid memory pointer\n");
177         }
178         if (bios_image) {
179                 /** when we are reading from a file the memory must be released */
180                 free(bios_image);
181         } else {
182                 /** when reading from the system memory, it must be unmapped */
183                 munmap(ptr, 0x10000);
184         }
185         /** Close the file handle */
186         close(fd_mem);
187         /** return 0 as OK ) */
188         return 0;
189 }