build.c

来自「linux 内核源代码」· C语言 代码 · 共 864 行 · 第 1/2 页

C
864
字号
	ubi_assert(ubi->min_io_size % ubi->hdrs_min_io_size == 0);	/* Calculate default aligned sizes of EC and VID headers */	ubi->ec_hdr_alsize = ALIGN(UBI_EC_HDR_SIZE, ubi->hdrs_min_io_size);	ubi->vid_hdr_alsize = ALIGN(UBI_VID_HDR_SIZE, ubi->hdrs_min_io_size);	dbg_msg("min_io_size      %d", ubi->min_io_size);	dbg_msg("hdrs_min_io_size %d", ubi->hdrs_min_io_size);	dbg_msg("ec_hdr_alsize    %d", ubi->ec_hdr_alsize);	dbg_msg("vid_hdr_alsize   %d", ubi->vid_hdr_alsize);	if (ubi->vid_hdr_offset == 0)		/* Default offset */		ubi->vid_hdr_offset = ubi->vid_hdr_aloffset =				      ubi->ec_hdr_alsize;	else {		ubi->vid_hdr_aloffset = ubi->vid_hdr_offset &						~(ubi->hdrs_min_io_size - 1);		ubi->vid_hdr_shift = ubi->vid_hdr_offset -						ubi->vid_hdr_aloffset;	}	/* Similar for the data offset */	if (ubi->leb_start == 0) {		ubi->leb_start = ubi->vid_hdr_offset + ubi->vid_hdr_alsize;		ubi->leb_start = ALIGN(ubi->leb_start, ubi->min_io_size);	}	dbg_msg("vid_hdr_offset   %d", ubi->vid_hdr_offset);	dbg_msg("vid_hdr_aloffset %d", ubi->vid_hdr_aloffset);	dbg_msg("vid_hdr_shift    %d", ubi->vid_hdr_shift);	dbg_msg("leb_start        %d", ubi->leb_start);	/* The shift must be aligned to 32-bit boundary */	if (ubi->vid_hdr_shift % 4) {		ubi_err("unaligned VID header shift %d",			ubi->vid_hdr_shift);		return -EINVAL;	}	/* Check sanity */	if (ubi->vid_hdr_offset < UBI_EC_HDR_SIZE ||	    ubi->leb_start < ubi->vid_hdr_offset + UBI_VID_HDR_SIZE ||	    ubi->leb_start > ubi->peb_size - UBI_VID_HDR_SIZE ||	    ubi->leb_start % ubi->min_io_size) {		ubi_err("bad VID header (%d) or data offsets (%d)",			ubi->vid_hdr_offset, ubi->leb_start);		return -EINVAL;	}	/*	 * It may happen that EC and VID headers are situated in one minimal	 * I/O unit. In this case we can only accept this UBI image in	 * read-only mode.	 */	if (ubi->vid_hdr_offset + UBI_VID_HDR_SIZE <= ubi->hdrs_min_io_size) {		ubi_warn("EC and VID headers are in the same minimal I/O unit, "			 "switch to read-only mode");		ubi->ro_mode = 1;	}	ubi->leb_size = ubi->peb_size - ubi->leb_start;	if (!(ubi->mtd->flags & MTD_WRITEABLE)) {		ubi_msg("MTD device %d is write-protected, attach in "			"read-only mode", ubi->mtd->index);		ubi->ro_mode = 1;	}	dbg_msg("leb_size         %d", ubi->leb_size);	dbg_msg("ro_mode          %d", ubi->ro_mode);	/*	 * Note, ideally, we have to initialize ubi->bad_peb_count here. But	 * unfortunately, MTD does not provide this information. We should loop	 * over all physical eraseblocks and invoke mtd->block_is_bad() for	 * each physical eraseblock. So, we skip ubi->bad_peb_count	 * uninitialized and initialize it after scanning.	 */	return 0;}/** * attach_mtd_dev - attach an MTD device. * @mtd_dev: MTD device name or number string * @vid_hdr_offset: VID header offset * @data_offset: data offset * * This function attaches an MTD device to UBI. It first treats @mtd_dev as the * MTD device name, and tries to open it by this name. If it is unable to open, * it tries to convert @mtd_dev to an integer and open the MTD device by its * number. Returns zero in case of success and a negative error code in case of * failure. */static int attach_mtd_dev(const char *mtd_dev, int vid_hdr_offset,			  int data_offset){	struct ubi_device *ubi;	struct mtd_info *mtd;	int i, err;	mtd = get_mtd_device_nm(mtd_dev);	if (IS_ERR(mtd)) {		int mtd_num;		char *endp;		if (PTR_ERR(mtd) != -ENODEV)			return PTR_ERR(mtd);		/*		 * Probably this is not MTD device name but MTD device number -		 * check this out.		 */		mtd_num = simple_strtoul(mtd_dev, &endp, 0);		if (*endp != '\0' || mtd_dev == endp) {			ubi_err("incorrect MTD device: \"%s\"", mtd_dev);			return -ENODEV;		}		mtd = get_mtd_device(NULL, mtd_num);		if (IS_ERR(mtd))			return PTR_ERR(mtd);	}	/* Check if we already have the same MTD device attached */	for (i = 0; i < ubi_devices_cnt; i++)		if (ubi_devices[i]->mtd->index == mtd->index) {			ubi_err("mtd%d is already attached to ubi%d",				mtd->index, i);			err = -EINVAL;			goto out_mtd;		}	ubi = ubi_devices[ubi_devices_cnt] = kzalloc(sizeof(struct ubi_device),						     GFP_KERNEL);	if (!ubi) {		err = -ENOMEM;		goto out_mtd;	}	ubi->ubi_num = ubi_devices_cnt;	ubi->mtd = mtd;	dbg_msg("attaching mtd%d to ubi%d: VID header offset %d data offset %d",		ubi->mtd->index, ubi_devices_cnt, vid_hdr_offset, data_offset);	ubi->vid_hdr_offset = vid_hdr_offset;	ubi->leb_start = data_offset;	err = io_init(ubi);	if (err)		goto out_free;	mutex_init(&ubi->buf_mutex);	ubi->peb_buf1 = vmalloc(ubi->peb_size);	if (!ubi->peb_buf1)		goto out_free;	ubi->peb_buf2 = vmalloc(ubi->peb_size);	if (!ubi->peb_buf2)		 goto out_free;#ifdef CONFIG_MTD_UBI_DEBUG	mutex_init(&ubi->dbg_buf_mutex);	ubi->dbg_peb_buf = vmalloc(ubi->peb_size);	if (!ubi->dbg_peb_buf)		 goto out_free;#endif	err = attach_by_scanning(ubi);	if (err) {		dbg_err("failed to attach by scanning, error %d", err);		goto out_free;	}	err = uif_init(ubi);	if (err)		goto out_detach;	ubi_msg("attached mtd%d to ubi%d", ubi->mtd->index, ubi_devices_cnt);	ubi_msg("MTD device name:            \"%s\"", ubi->mtd->name);	ubi_msg("MTD device size:            %llu MiB", ubi->flash_size >> 20);	ubi_msg("physical eraseblock size:   %d bytes (%d KiB)",		ubi->peb_size, ubi->peb_size >> 10);	ubi_msg("logical eraseblock size:    %d bytes", ubi->leb_size);	ubi_msg("number of good PEBs:        %d", ubi->good_peb_count);	ubi_msg("number of bad PEBs:         %d", ubi->bad_peb_count);	ubi_msg("smallest flash I/O unit:    %d", ubi->min_io_size);	ubi_msg("VID header offset:          %d (aligned %d)",		ubi->vid_hdr_offset, ubi->vid_hdr_aloffset);	ubi_msg("data offset:                %d", ubi->leb_start);	ubi_msg("max. allowed volumes:       %d", ubi->vtbl_slots);	ubi_msg("wear-leveling threshold:    %d", CONFIG_MTD_UBI_WL_THRESHOLD);	ubi_msg("number of internal volumes: %d", UBI_INT_VOL_COUNT);	ubi_msg("number of user volumes:     %d",		ubi->vol_count - UBI_INT_VOL_COUNT);	ubi_msg("available PEBs:             %d", ubi->avail_pebs);	ubi_msg("total number of reserved PEBs: %d", ubi->rsvd_pebs);	ubi_msg("number of PEBs reserved for bad PEB handling: %d",		ubi->beb_rsvd_pebs);	ubi_msg("max/mean erase counter: %d/%d", ubi->max_ec, ubi->mean_ec);	/* Enable the background thread */	if (!DBG_DISABLE_BGT) {		ubi->thread_enabled = 1;		wake_up_process(ubi->bgt_thread);	}	ubi_devices_cnt += 1;	return 0;out_detach:	ubi_eba_close(ubi);	ubi_wl_close(ubi);	vfree(ubi->vtbl);out_free:	vfree(ubi->peb_buf1);	vfree(ubi->peb_buf2);#ifdef CONFIG_MTD_UBI_DEBUG	vfree(ubi->dbg_peb_buf);#endif	kfree(ubi);out_mtd:	put_mtd_device(mtd);	ubi_devices[ubi_devices_cnt] = NULL;	return err;}/** * detach_mtd_dev - detach an MTD device. * @ubi: UBI device description object */static void detach_mtd_dev(struct ubi_device *ubi){	int ubi_num = ubi->ubi_num, mtd_num = ubi->mtd->index;	dbg_msg("detaching mtd%d from ubi%d", ubi->mtd->index, ubi_num);	uif_close(ubi);	ubi_eba_close(ubi);	ubi_wl_close(ubi);	vfree(ubi->vtbl);	put_mtd_device(ubi->mtd);	vfree(ubi->peb_buf1);	vfree(ubi->peb_buf2);#ifdef CONFIG_MTD_UBI_DEBUG	vfree(ubi->dbg_peb_buf);#endif	kfree(ubi_devices[ubi_num]);	ubi_devices[ubi_num] = NULL;	ubi_devices_cnt -= 1;	ubi_assert(ubi_devices_cnt >= 0);	ubi_msg("mtd%d is detached from ubi%d", mtd_num, ubi_num);}static int __init ubi_init(void){	int err, i, k;	/* Ensure that EC and VID headers have correct size */	BUILD_BUG_ON(sizeof(struct ubi_ec_hdr) != 64);	BUILD_BUG_ON(sizeof(struct ubi_vid_hdr) != 64);	if (mtd_devs > UBI_MAX_DEVICES) {		printk("UBI error: too many MTD devices, maximum is %d\n",		       UBI_MAX_DEVICES);		return -EINVAL;	}	ubi_class = class_create(THIS_MODULE, UBI_NAME_STR);	if (IS_ERR(ubi_class))		return PTR_ERR(ubi_class);	err = class_create_file(ubi_class, &ubi_version);	if (err)		goto out_class;	/* Attach MTD devices */	for (i = 0; i < mtd_devs; i++) {		struct mtd_dev_param *p = &mtd_dev_param[i];		cond_resched();		err = attach_mtd_dev(p->name, p->vid_hdr_offs, p->data_offs);		if (err)			goto out_detach;	}	return 0;out_detach:	for (k = 0; k < i; k++)		detach_mtd_dev(ubi_devices[k]);	class_remove_file(ubi_class, &ubi_version);out_class:	class_destroy(ubi_class);	return err;}module_init(ubi_init);static void __exit ubi_exit(void){	int i, n = ubi_devices_cnt;	for (i = 0; i < n; i++)		detach_mtd_dev(ubi_devices[i]);	class_remove_file(ubi_class, &ubi_version);	class_destroy(ubi_class);}module_exit(ubi_exit);/** * bytes_str_to_int - convert a string representing number of bytes to an * integer. * @str: the string to convert * * This function returns positive resulting integer in case of success and a * negative error code in case of failure. */static int __init bytes_str_to_int(const char *str){	char *endp;	unsigned long result;	result = simple_strtoul(str, &endp, 0);	if (str == endp || result < 0) {		printk("UBI error: incorrect bytes count: \"%s\"\n", str);		return -EINVAL;	}	switch (*endp) {	case 'G':		result *= 1024;	case 'M':		result *= 1024;	case 'K':	case 'k':		result *= 1024;		if (endp[1] == 'i' && (endp[2] == '\0' ||			  endp[2] == 'B'  || endp[2] == 'b'))			endp += 2;	case '\0':		break;	default:		printk("UBI error: incorrect bytes count: \"%s\"\n", str);		return -EINVAL;	}	return result;}/** * ubi_mtd_param_parse - parse the 'mtd=' UBI parameter. * @val: the parameter value to parse * @kp: not used * * This function returns zero in case of success and a negative error code in * case of error. */static int __init ubi_mtd_param_parse(const char *val, struct kernel_param *kp){	int i, len;	struct mtd_dev_param *p;	char buf[MTD_PARAM_LEN_MAX];	char *pbuf = &buf[0];	char *tokens[3] = {NULL, NULL, NULL};	if (mtd_devs == UBI_MAX_DEVICES) {		printk("UBI error: too many parameters, max. is %d\n",		       UBI_MAX_DEVICES);		return -EINVAL;	}	len = strnlen(val, MTD_PARAM_LEN_MAX);	if (len == MTD_PARAM_LEN_MAX) {		printk("UBI error: parameter \"%s\" is too long, max. is %d\n",		       val, MTD_PARAM_LEN_MAX);		return -EINVAL;	}	if (len == 0) {		printk("UBI warning: empty 'mtd=' parameter - ignored\n");		return 0;	}	strcpy(buf, val);	/* Get rid of the final newline */	if (buf[len - 1] == '\n')		buf[len - 1] = '\0';	for (i = 0; i < 3; i++)		tokens[i] = strsep(&pbuf, ",");	if (pbuf) {		printk("UBI error: too many arguments at \"%s\"\n", val);		return -EINVAL;	}	p = &mtd_dev_param[mtd_devs];	strcpy(&p->name[0], tokens[0]);	if (tokens[1])		p->vid_hdr_offs = bytes_str_to_int(tokens[1]);	if (tokens[2])		p->data_offs = bytes_str_to_int(tokens[2]);	if (p->vid_hdr_offs < 0)		return p->vid_hdr_offs;	if (p->data_offs < 0)		return p->data_offs;	mtd_devs += 1;	return 0;}module_param_call(mtd, ubi_mtd_param_parse, NULL, NULL, 000);MODULE_PARM_DESC(mtd, "MTD devices to attach. Parameter format: "		      "mtd=<name|num>[,<vid_hdr_offs>,<data_offs>]. "		      "Multiple \"mtd\" parameters may be specified.\n"		      "MTD devices may be specified by their number or name. "		      "Optional \"vid_hdr_offs\" and \"data_offs\" parameters "		      "specify UBI VID header position and data starting "		      "position to be used by UBI.\n"		      "Example: mtd=content,1984,2048 mtd=4 - attach MTD device"		      "with name content using VID header offset 1984 and data "		      "start 2048, and MTD device number 4 using default "		      "offsets");MODULE_VERSION(__stringify(UBI_VERSION));MODULE_DESCRIPTION("UBI - Unsorted Block Images");MODULE_AUTHOR("Artem Bityutskiy");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?