qcom platform 子系统(5)

******************************************************************************/
/*------------------------------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;
}

你可能感兴趣的:(kernel)