| Ramoops oops/panic logger | 
 | ========================= | 
 |  | 
 | Sergiu Iordache <sergiu@chromium.org> | 
 |  | 
 | Updated: 17 November 2011 | 
 |  | 
 | 0. Introduction | 
 |  | 
 | Ramoops is an oops/panic logger that writes its logs to RAM before the system | 
 | crashes. It works by logging oopses and panics in a circular buffer. Ramoops | 
 | needs a system with persistent RAM so that the content of that area can | 
 | survive after a restart. | 
 |  | 
 | 1. Ramoops concepts | 
 |  | 
 | Ramoops uses a predefined memory area to store the dump. The start and size of | 
 | the memory area are set using two variables: | 
 |   * "mem_address" for the start | 
 |   * "mem_size" for the size. The memory size will be rounded down to a | 
 |   power of two. | 
 |  | 
 | The memory area is divided into "record_size" chunks (also rounded down to | 
 | power of two) and each oops/panic writes a "record_size" chunk of | 
 | information. | 
 |  | 
 | Dumping both oopses and panics can be done by setting 1 in the "dump_oops" | 
 | variable while setting 0 in that variable dumps only the panics. | 
 |  | 
 | The module uses a counter to record multiple dumps but the counter gets reset | 
 | on restart (i.e. new dumps after the restart will overwrite old ones). | 
 |  | 
 | Ramoops also supports software ECC protection of persistent memory regions. | 
 | This might be useful when a hardware reset was used to bring the machine back | 
 | to life (i.e. a watchdog triggered). In such cases, RAM may be somewhat | 
 | corrupt, but usually it is restorable. | 
 |  | 
 | 2. Setting the parameters | 
 |  | 
 | Setting the ramoops parameters can be done in 2 different manners: | 
 |  1. Use the module parameters (which have the names of the variables described | 
 |  as before). | 
 |  2. Use a platform device and set the platform data. The parameters can then | 
 |  be set through that platform data. An example of doing that is: | 
 |  | 
 | #include <linux/pstore_ram.h> | 
 | [...] | 
 |  | 
 | static struct ramoops_platform_data ramoops_data = { | 
 |         .mem_size               = <...>, | 
 |         .mem_address            = <...>, | 
 |         .record_size            = <...>, | 
 |         .dump_oops              = <...>, | 
 |         .ecc                    = <...>, | 
 | }; | 
 |  | 
 | static struct platform_device ramoops_dev = { | 
 |         .name = "ramoops", | 
 |         .dev = { | 
 |                 .platform_data = &ramoops_data, | 
 |         }, | 
 | }; | 
 |  | 
 | [... inside a function ...] | 
 | int ret; | 
 |  | 
 | ret = platform_device_register(&ramoops_dev); | 
 | if (ret) { | 
 | 	printk(KERN_ERR "unable to register platform device\n"); | 
 | 	return ret; | 
 | } | 
 |  | 
 | 3. Dump format | 
 |  | 
 | The data dump begins with a header, currently defined as "====" followed by a | 
 | timestamp and a new line. The dump then continues with the actual data. | 
 |  | 
 | 4. Reading the data | 
 |  | 
 | The dump data can be read from the pstore filesystem. The format for these | 
 | files is "dmesg-ramoops-N", where N is the record number in memory. To delete | 
 | a stored record from RAM, simply unlink the respective pstore file. |