2010年1月27日 星期三

Linux Kernel(10.3)- Command line partition table parsing


MTD Partition除了在code中寫死以外,其實還可以透過一些parsers來作規劃,這一章就要來教大家如何使用"Command line partition table parsing"。首先必須在kernel中啟用"Command line partition table parsing",請參照下圖。

這樣kernel就可以支援"Command line partition table parsing",然後我們還是拿mtdram.c的code來改(紅色的部份)。

/*
 * mtdram - a test mtd device
 * Author: Alexander Larsson <alex@cendio.se>
 *
 * Copyright (c) 1999 Alexander Larsson alex@cendio.se>
 * Copyright (c) 2005 Joern Engel <joern@wh.fh-wedel.de>
 *
 * This code is GPL
 *
 */

#include <linux/module.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <linux/vmalloc.h>
#include <linux/init.h>
#include <linux/mtd/compatmac.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/mtdram.h>
#include <linux/mtd/partitions.h>

static unsigned long total_size = CONFIG_MTDRAM_TOTAL_SIZE;
static unsigned long erase_size = CONFIG_MTDRAM_ERASE_SIZE;
#define MTDRAM_TOTAL_SIZE (total_size * 1024)
#define MTDRAM_ERASE_SIZE (erase_size * 1024)

#ifdef MODULE
module_param(total_size, ulong, 0);
MODULE_PARM_DESC(total_size, "Total device size in KiB");
module_param(erase_size, ulong, 0);
MODULE_PARM_DESC(erase_size, "Device erase block size in KiB");
#endif

// We could store these in the mtd structure, but we only support 1 device..
static struct mtd_info *mtd_info;
static char partitioned = 0;

static int ram_erase(struct mtd_info *mtd, struct erase_info *instr)
{
    if (instr->addr + instr->len > mtd->size)
        return -EINVAL;

    memset((char *)mtd->priv + instr->addr, 0xff, instr->len);

    instr->state = MTD_ERASE_DONE;
    mtd_erase_callback(instr);

    return 0;
}

static int ram_point(struct mtd_info *mtd, loff_t from, size_t len,
        size_t *retlen, void **virt, resource_size_t *phys)
{
    if (from + len > mtd->size)
        return -EINVAL;

    /* can we return a physical address with this driver? */
    if (phys)
        return -EINVAL;

    *virt = mtd->priv + from;
    *retlen = len;
    return 0;
}

static void ram_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
{
}

/*
 * Allow NOMMU mmap() to directly map the device (if not NULL)
 * - return the address to which the offset maps
 * - return -ENOSYS to indicate refusal to do the mapping
 */
static unsigned long ram_get_unmapped_area(struct mtd_info *mtd,
                       unsigned long len,
                       unsigned long offset,
                       unsigned long flags)
{
    return (unsigned long) mtd->priv + offset;
}

static int ram_read(struct mtd_info *mtd, loff_t from, size_t len,
        size_t *retlen, u_char *buf)
{
    if (from + len > mtd->size)
        return -EINVAL;

    memcpy(buf, mtd->priv + from, len);

    *retlen = len;
    return 0;
}

static int ram_write(struct mtd_info *mtd, loff_t to, size_t len,
        size_t *retlen, const u_char *buf)
{
    if (to + len > mtd->size)
        return -EINVAL;

    memcpy((char *)mtd->priv + to, buf, len);

    *retlen = len;
    return 0;
}

static void __exit cleanup_mtdram(void)
{
    if (mtd_info) {

        if (mtd_has_partitions() && partitioned) {
            del_mtd_partitions(mtd_info);
        } else {
            del_mtd_device(mtd_info);
        }

        vfree(mtd_info->priv);
        kfree(mtd_info);
    }
}

int mtdram_init_device(struct mtd_info *mtd, void *mapped_address,
        unsigned long size, char *name)
{
    memset(mtd, 0, sizeof(*mtd));

    /* Setup the MTD structure */
    mtd->name = name;
    mtd->type = MTD_RAM;
    mtd->flags = MTD_CAP_RAM;
    mtd->size = size;
    mtd->writesize = 1;
    mtd->erasesize = MTDRAM_ERASE_SIZE;
    mtd->priv = mapped_address;

    mtd->owner = THIS_MODULE;
    mtd->erase = ram_erase;
    mtd->point = ram_point;
    mtd->unpoint = ram_unpoint;
    mtd->get_unmapped_area = ram_get_unmapped_area;
    mtd->read = ram_read;
    mtd->write = ram_write;

    if (mtd_has_partitions()) {
        struct mtd_partition *mtd_parts = NULL;
        static const char *probes[] =
                    { "cmdlinepart", NULL };
        int nb_parts = 0;
        printk("has partitions\n");
        if (mtd_has_cmdlinepart()) {
            printk("has probs\n");
            nb_parts = parse_mtd_partitions(mtd, probes, &mtd_parts, 0);
        }
        if (nb_parts > 0) {
            printk("partitioned\n");
            partitioned = 1;
            return add_mtd_partitions(mtd, mtd_parts, nb_parts);
        }
    }

    if (add_mtd_device(mtd)) {
        return -EIO;
    }

    return 0;
}

static int __init init_mtdram(void)
{
    void *addr;
    int err;

    if (!total_size)
        return -EINVAL;

    /* Allocate some memory */
    mtd_info = kmalloc(sizeof(struct mtd_info), GFP_KERNEL);
    if (!mtd_info)
        return -ENOMEM;

    addr = vmalloc(MTDRAM_TOTAL_SIZE);
    if (!addr) {
        kfree(mtd_info);
        mtd_info = NULL;
        return -ENOMEM;
    }
    err = mtdram_init_device(mtd_info, 
                  addr, MTDRAM_TOTAL_SIZE, "brook_flash");
    if (err) {
        vfree(addr);
        kfree(mtd_info);
        mtd_info = NULL;
        return err;
    }
    memset(mtd_info->priv, 0xff, MTDRAM_TOTAL_SIZE);
    return err;
}

module_init(init_mtdram);
module_exit(cleanup_mtdram);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Alexander Larsson <alexl@redhat.com>");
MODULE_DESCRIPTION("Simulated MTD driver for testing");




1 則留言:

  1. CONFIG_MTD_CMDLINE_PARTS: │
    │ │
    │ Allow generic configuration of the MTD partition tables via the kernel │
    │ command line. Multiple flash resources are supported for hardware where │
    │ different kinds of flash memory are available. │
    │ │
    │ You will still need the parsing functions to be called by the driver │
    │ for your particular device. It won't happen automatically. The │
    │ SA1100 map driver (CONFIG_MTD_SA1100) has an option for this, for │
    │ example. │
    │ │
    │ The format for the command line is as follows: │
    │ │
    │ mtdparts=[; := :[,] │
    │ := [@offset][][ro] │
    │ := unique id used in mapping driver/device │
    │ := standard linux memsize OR "-" to denote all │
    │ remaining space │
    │ := (NAME) │
    │ │
    │ Due to the way Linux handles the command line, no spaces are │
    │ allowed in the partition definition, including mtd id's and partition │
    │ names.

    回覆刪除

熱門文章