******************************************************************************/
/*------------------------------ramdump_device--------------------------------*/
/******************************************************************************/
struct ramdump_device {
char name[256];
unsigned int data_ready;
unsigned int consumer_present;
int ramdump_status;
struct completion ramdump_complete;
struct miscdevice device;
wait_queue_head_t dump_wait_q;
int nsegments;
struct ramdump_segment *segments;
size_t elfcore_size;
char *elfcore_buf;
struct dma_attrs attrs;
};
struct ramdump_segment {
unsigned long address;
void *v_address;
unsigned long size;
};
void *create_ramdump_device(const char *dev_name, struct device *parent)
{
int ret;
struct ramdump_device *rd_dev;
rd_dev = kzalloc(sizeof(struct ramdump_device), GFP_KERNEL);
snprintf(rd_dev->name, ARRAY_SIZE(rd_dev->name), "ramdump_%s",
dev_name);
init_completion(&rd_dev->ramdump_complete);
rd_dev->device.minor = MISC_DYNAMIC_MINOR;
rd_dev->device.name = rd_dev->name;
rd_dev->device.fops = &ramdump_file_ops;
rd_dev->device.parent = parent;
init_waitqueue_head(&rd_dev->dump_wait_q);
ret = misc_register(&rd_dev->device);
return (void *)rd_dev;
}
另外注意这个用法:省的写很长的代码行
#ifndef ARRAY_SIZE
# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#endif
root@gemini:/dev # ls -al | grep ramdump
crw-r----- system system 10, 66 1970-02-24 03:47 ramdump_AR6320
crw-r----- system system 10, 88 1970-02-24 03:47 ramdump_a530_zap
crw-r----- system system 10, 55 1970-02-24 03:47 ramdump_adsp
crw-r----- system system 10, 47 1970-02-24 03:47 ramdump_adsp_rh
crw-r----- system system 10, 34 1970-02-24 03:47 ramdump_cpe
crw-r----- system system 10, 53 1970-02-24 03:47 ramdump_modem
crw-r----- system system 10, 54 1970-02-24 03:47 ramdump_slpi
crw-r----- system system 10, 48 1970-02-24 03:47 ramdump_smem
crw-r----- system system 10, 89 1970-02-24 03:47 ramdump_venus
drv->subsys_desc.ramdump = modem_ramdump;
static int modem_ramdump(int enable, const struct subsys_desc *subsys)
{
struct modem_data *drv = subsys_to_drv(subsys);
pil_do_ramdump(&drv->q6->desc, drv->ramdump_dev);
}
/**
* pil_do_ramdump() - Ramdump an image
* @desc: descriptor from pil_desc_init()
* @ramdump_dev: ramdump device returned from create_ramdump_device()
*
* Calls the ramdump API with a list of segments generated from the addresses
* that the descriptor corresponds to.
*/
int pil_do_ramdump(struct pil_desc *desc, void *ramdump_dev)
{
struct pil_priv *priv = desc->priv;
struct pil_seg *seg;
int count = 0;
struct ramdump_segment *ramdump_segs, *s;
list_for_each_entry(seg, &priv->segs, list)
count++;
ramdump_segs = kcalloc(count, sizeof(*ramdump_segs), GFP_KERNEL);
s = ramdump_segs;
list_for_each_entry(seg, &priv->segs, list) {
s->address = seg->paddr;
s->size = seg->sz;
s++;
}
ret = do_elf_ramdump(ramdump_dev, ramdump_segs, count);
kfree(ramdump_segs);
}/*各个段的描述来自:pil*/
int
do_elf_ramdump(void *handle, struct ramdump_segment *segments, int nsegments)
{
return _do_ramdump(handle, segments, nsegments, true);
}
ELF文件原名Executable and Linking Format,译为“可执行可连接格式”。
ELF规范中把ELF文件宽泛的称为“目标文件”,这与我们平时的理解不同。
一般的,我们把编译但没有链接的文件(比如Linux下的.o文件)称为目标文件。而ELF文件仅指链接好的可执行文件。
分别是ELF头(ELF header)、程序头表(Program header table)、节(Section)和节头表(Section header table)
/*把要dump的数据转换为elf格式*/
static int _do_ramdump(void *handle, struct ramdump_segment *segments,
int nsegments, bool use_elf)
{
int ret, i;
struct ramdump_device *rd_dev = (struct ramdump_device *)handle;
Elf32_Phdr *phdr;
Elf32_Ehdr *ehdr;
unsigned long offset;
for (i = 0; i < nsegments; i++)
segments[i].size = PAGE_ALIGN(segments[i].size);
rd_dev->segments = segments;
rd_dev->nsegments = nsegments;
if (use_elf) {
rd_dev->elfcore_size = sizeof(*ehdr) +
sizeof(*phdr) * nsegments;
ehdr = kzalloc(rd_dev->elfcore_size, GFP_KERNEL);
rd_dev->elfcore_buf = (char *)ehdr;
}
/* Tell userspace that the data is ready */
wake_up(&rd_dev->dump_wait_q);
/* Wait (with a timeout) to let the ramdump complete */
ret = wait_for_completion_timeout(&rd_dev->ramdump_complete,
msecs_to_jiffies(RAMDUMP_WAIT_MSECS));
}
static ssize_t ramdump_read(struct file *filep, char __user *buf, size_t count,
loff_t *pos)
{
struct ramdump_device *rd_dev = container_of(filep->private_data,
struct ramdump_device, device);
}
static unsigned int ramdump_poll(struct file *filep,
struct poll_table_struct *wait)
{
struct ramdump_device *rd_dev = container_of(filep->private_data,
struct ramdump_device, device);
unsigned int mask = 0;
if (rd_dev->data_ready)
mask |= (POLLIN | POLLRDNORM);
poll_wait(filep, &rd_dev->dump_wait_q, wait);
return mask;
}