Exemple #1
0
int atags_to_fdt(void *atag_list, void *fdt, int total_space)
{
	struct tag *atag = atag_list;
	/* In the case of 64 bits memory size, need to reserve 2 cells for
	 * address and size for each bank */

/* IAMROOT-12A:
 * ------------
 * 64비트 시스템의 경우 한 개 뱅크당 주소와 사이즈((2 + 2) x sizeof(int32))
 */
	uint32_t mem_reg_property[2 * 2 * NR_BANKS];
	int memcount = 0;
	int ret, memsize;

	/* make sure we've got an aligned pointer */
	if ((u32)atag_list & 0x3)
		return 1;

/* IAMROOT-12A:
 * ------------
 * atag/DTB 포인터에서 DTB 매직넘버를 발견하면 이미 DTB가 존재하는 것으로 파악이되어
 * ATAG를 컨버전할 필요 없으므로 성공으로 리턴 
 */
	/* if we get a DTB here we're done already */
	if (*(u32 *)atag_list == fdt32_to_cpu(FDT_MAGIC))
	       return 0;

/* IAMROOT-12A:
 * ------------
 * 처음에 오는 태크가 ATAG_CORE가 아니거나 사이즈가 맞지않으면 실패(1)로 리턴
 */
	/* validate the ATAG */
	if (atag->hdr.tag != ATAG_CORE ||
	    (atag->hdr.size != tag_size(tag_core) &&
	     atag->hdr.size != 2))
		return 1;

	/* let's give it all the room it could need */
	ret = fdt_open_into(fdt, fdt, total_space);
	if (ret < 0)
		return ret;

/* IAMROOT-12A:
 * ------------
 * atag_list는 atag 개채의 묶음.
 * for_each_tag()를 수행 시 atag에 하나의 ATAG를 가리키는 포인터가 담김
 * 태그는 3개(ATAG_CMDLINE, ATAG_MEM, ATAG_INITRD2)만 디바이스트리로 컨버전
 *    - ATAG_CMDLINE(cmdline) ---> DTB:/chosen 노드 -> bootargs 프로퍼티
 *    - ATAG_MEM(u.mem.start & u.mem.size x N뱅크) ---> DTB:/memory 노드 -> reg 프로퍼티
 *    - ATAG_INITRD2(u.initrd.start & u.initrd.size) ---> DTB:/chosen 노드 -> linux,initrd-start
 *                                                   ---> DTB:/chosen 노드 -> linux,initrd-end
 */
	for_each_tag(atag, atag_list) {
		if (atag->hdr.tag == ATAG_CMDLINE) {
			/* Append the ATAGS command line to the device tree
			 * command line.
			 * NB: This means that if the same parameter is set in
			 * the device tree and in the tags, the one from the
			 * tags will be chosen.
			 */
			if (do_extend_cmdline)
				merge_fdt_bootargs(fdt,
						   atag->u.cmdline.cmdline);
			else
				setprop_string(fdt, "/chosen", "bootargs",
					       atag->u.cmdline.cmdline);
		} else if (atag->hdr.tag == ATAG_MEM) {
			if (memcount >= sizeof(mem_reg_property)/4)
				continue;
			if (!atag->u.mem.size)
				continue;
			memsize = get_cell_size(fdt);

/* IAMROOT-12A:
 * ------------
 * memsize=2인 경우 64비트
 * ATAG_MEM은 여러 개가 존재할 수 있다.
 */
			if (memsize == 2) {
				/* if memsize is 2, that means that
				 * each data needs 2 cells of 32 bits,
				 * so the data are 64 bits */
				uint64_t *mem_reg_prop64 =
					(uint64_t *)mem_reg_property;
				mem_reg_prop64[memcount++] =
					cpu_to_fdt64(atag->u.mem.start);
				mem_reg_prop64[memcount++] =
					cpu_to_fdt64(atag->u.mem.size);
			} else {
				mem_reg_property[memcount++] =
					cpu_to_fdt32(atag->u.mem.start);
				mem_reg_property[memcount++] =
					cpu_to_fdt32(atag->u.mem.size);
			}

		} else if (atag->hdr.tag == ATAG_INITRD2) {
			uint32_t initrd_start, initrd_size;
			initrd_start = atag->u.initrd.start;
			initrd_size = atag->u.initrd.size;
			setprop_cell(fdt, "/chosen", "linux,initrd-start",
					initrd_start);
			setprop_cell(fdt, "/chosen", "linux,initrd-end",
					initrd_start + initrd_size);
		}
	}

	if (memcount) {
		setprop(fdt, "/memory", "reg", mem_reg_property,
			4 * memcount * memsize);
	}

	return fdt_pack(fdt);
}
Exemple #2
0
/*
 * Convert and fold provided ATAGs into the provided FDT.
 *
 * REturn values:
 *    = 0 -> pretend success
 *    = 1 -> bad ATAG (may retry with another possible ATAG pointer)
 *    < 0 -> error from libfdt
 */
int atags_to_fdt(void *atag_list, void *fdt, int total_space)
{
	struct tag *atag = atag_list;
	/* In the case of 64 bits memory size, need to reserve 2 cells for
	 * address and size for each bank */
	uint32_t mem_reg_property[2 * 2 * NR_BANKS];
	int memcount = 0;
	int ret, memsize;

	/* make sure we've got an aligned pointer */
	if ((u32)atag_list & 0x3)
		return 1;

	/* if we get a DTB here we're done already */
	if (*(u32 *)atag_list == fdt32_to_cpu(FDT_MAGIC))
	       return 0;

	/* validate the ATAG */
	if (atag->hdr.tag != ATAG_CORE ||
	    (atag->hdr.size != tag_size(tag_core) &&
	     atag->hdr.size != 2))
		return 1;

	/* let's give it all the room it could need */
	ret = fdt_open_into(fdt, fdt, total_space);
	if (ret < 0)
		return ret;

	for_each_tag(atag, atag_list) {
		if (atag->hdr.tag == ATAG_CMDLINE) {
			/* Append the ATAGS command line to the device tree
			 * command line.
			 * NB: This means that if the same parameter is set in
			 * the device tree and in the tags, the one from the
			 * tags will be chosen.
			 */
			if (do_extend_cmdline)
				merge_fdt_bootargs(fdt,
						   atag->u.cmdline.cmdline);
			else
				setprop_string(fdt, "/chosen", "bootargs",
					       atag->u.cmdline.cmdline);
		} else if (atag->hdr.tag == ATAG_MEM) {
			if (memcount >= sizeof(mem_reg_property)/4)
				continue;
			if (!atag->u.mem.size)
				continue;
			memsize = get_cell_size(fdt);

			if (memsize == 2) {
				/* if memsize is 2, that means that
				 * each data needs 2 cells of 32 bits,
				 * so the data are 64 bits */
				uint64_t *mem_reg_prop64 =
					(uint64_t *)mem_reg_property;
				mem_reg_prop64[memcount++] =
					cpu_to_fdt64(atag->u.mem.start);
				mem_reg_prop64[memcount++] =
					cpu_to_fdt64(atag->u.mem.size);
			} else {
				mem_reg_property[memcount++] =
					cpu_to_fdt32(atag->u.mem.start);
				mem_reg_property[memcount++] =
					cpu_to_fdt32(atag->u.mem.size);
			}

		} else if (atag->hdr.tag == ATAG_INITRD2) {
			uint32_t initrd_start, initrd_size;
			initrd_start = atag->u.initrd.start;
			initrd_size = atag->u.initrd.size;
			setprop_cell(fdt, "/chosen", "linux,initrd-start",
					initrd_start);
			setprop_cell(fdt, "/chosen", "linux,initrd-end",
					initrd_start + initrd_size);
		}
	}

	if (memcount) {
		setprop(fdt, "/memory", "reg", mem_reg_property,
			4 * memcount * memsize);
	}

	return fdt_pack(fdt);
}
/*
 * Convert and fold provided ATAGs into the provided FDT.
 *
 * REturn values:
 *    = 0 -> pretend success
 *    = 1 -> bad ATAG (may retry with another possible ATAG pointer)
 *    < 0 -> error from libfdt
 */
int atags_to_fdt(void *atag_list, void *fdt, int total_space)
{
	struct tag *atag = atag_list;
	/* In the case of 64 bits memory size, need to reserve 2 cells for
	 * address and size for each bank */
	uint32_t mem_reg_property[2 * 2 * NR_BANKS];
	int memcount = 0;
	int ret, memsize;

	/* make sure we've got an aligned pointer */
	if ((u32)atag_list & 0x3)
		return 1;

	/* if we get a DTB here we're done already */
	if (*(u32 *)atag_list == fdt32_to_cpu(FDT_MAGIC))
	       return 0;

	/* validate the ATAG */
	if (atag->hdr.tag != ATAG_CORE ||
	    (atag->hdr.size != tag_size(tag_core) &&
	     atag->hdr.size != 2))
		return 1;

	/* let's give it all the room it could need */
	ret = fdt_open_into(fdt, fdt, total_space);
	if (ret < 0)
		return ret;

	for_each_tag(atag, atag_list) {
		if (atag->hdr.tag == ATAG_CMDLINE) {
			/* Append the ATAGS command line to the device tree
			 * command line.
			 * NB: This means that if the same parameter is set in
			 * the device tree and in the tags, the one from the
			 * tags will be chosen.
			 */
			if (do_extend_cmdline)
				merge_fdt_bootargs(fdt,
						   atag->u.cmdline.cmdline);
			else
				setprop_string(fdt, "/chosen", "bootargs",
					       atag->u.cmdline.cmdline);
		} else if (atag->hdr.tag == ATAG_MEM) {
			if (memcount >= sizeof(mem_reg_property)/4)
				continue;
			if (!atag->u.mem.size)
				continue;
			memsize = get_cell_size(fdt);

			if (memsize == 2) {
				/* if memsize is 2, that means that
				 * each data needs 2 cells of 32 bits,
				 * so the data are 64 bits */
				uint64_t *mem_reg_prop64 =
					(uint64_t *)mem_reg_property;
				mem_reg_prop64[memcount++] =
					cpu_to_fdt64(atag->u.mem.start);
				mem_reg_prop64[memcount++] =
					cpu_to_fdt64(atag->u.mem.size);
			} else {
				mem_reg_property[memcount++] =
					cpu_to_fdt32(atag->u.mem.start);
				mem_reg_property[memcount++] =
					cpu_to_fdt32(atag->u.mem.size);
			}

		} else if (atag->hdr.tag == ATAG_INITRD2) {
			uint32_t initrd_start, initrd_size;
			initrd_start = atag->u.initrd.start;
			initrd_size = atag->u.initrd.size;
			setprop_cell(fdt, "/chosen", "linux,initrd-start",
					initrd_start);
			setprop_cell(fdt, "/chosen", "linux,initrd-end",
					initrd_start + initrd_size);
		} else if (atag->hdr.tag == ATAG_BLUETOOTH) {
			setprop_values(fdt, "/chosen", "linux,bt_mac",
				(unsigned char *)(&atag->u), (atag->hdr.size-2)*sizeof(__u32));
		} else if (atag->hdr.tag == ATAG_MSM_WIFI) {
			#define NVS_MAX_SIZE	0x800U
			#define NVS_LEN_OFFSET	0x0C
			#define NVS_DATA_OFFSET	0x40
			char append[] = "\nsd_oobonly=1\nbtc_params80=0\nbtc_params6=30\n";
			__u32 len = 0;
			__u32 full_len = (atag->hdr.size-2)*sizeof(__u32);
			// check that we have enought space for get len
			if (full_len > NVS_LEN_OFFSET)
				memcpy(&len, (unsigned char *)(&atag->u) + NVS_LEN_OFFSET, sizeof(len));
			// len is less than full block size
			if (len > (NVS_MAX_SIZE - NVS_DATA_OFFSET))
				len = (NVS_MAX_SIZE - NVS_DATA_OFFSET);
			// len is less than atag block size
			if (len > full_len)
				len = full_len;
			// we have enought space for add additional params
			if ((len + strlen(append) + 1) <= full_len) {
				// block is finished by zero
				if (((unsigned char *)(&atag->u))[NVS_DATA_OFFSET + len] == 0)
					len --;
				//copy additional params
				memcpy(
					(unsigned char *)(&atag->u) + NVS_DATA_OFFSET + len,
					append,
					strlen(append) + 1
				);
				len += strlen(append);
				len ++;
			}
			// finaly save new wifi calibration
			setprop_values(fdt, "/chosen", "linux,wifi-calibration",
				(unsigned char *)(&atag->u) + NVS_DATA_OFFSET, len);
		} else if (atag->hdr.tag == ATAG_MSM_AWB_CAL) {
			setprop_values(fdt, "/chosen", "linux,awb_cal",
				(unsigned char *)(&atag->u), (atag->hdr.size-2)*sizeof(__u32));
		} else if (atag->hdr.tag == ATAG_MFG_GPIO_TABLE) {
			setprop_values(fdt, "/chosen", "linux,gpio_table",
				(unsigned char *)(&atag->u), (atag->hdr.size-2)*sizeof(__u32));
		} else if (atag->hdr.tag == ATAG_MSM_PARTITION) {
			setprop_values(fdt, "/chosen", "linux,msm_partitions",
				(unsigned char *)(&atag->u), (atag->hdr.size-2)*sizeof(__u32));
		} else if (atag->hdr.tag == ATAG_MEMSIZE) {
			setprop_cell(fdt, "/chosen", "linux,memsize",
					atag->u.revision.rev);
		} else if (atag->hdr.tag == ATAG_ALS) {
			setprop_cell(fdt, "/chosen", "linux,als_calibration",
					atag->u.als_kadc.kadc);
		} else if (atag->hdr.tag == ATAG_ENGINEERID) {
			setprop_cell(fdt, "/chosen", "linux,engineerid",
					atag->u.revision.rev);
		} else if (atag->hdr.tag == ATAG_SMI) {
			setprop_cell(fdt, "/chosen", "linux,smi",
					atag->u.mem.size);
		} else if (atag->hdr.tag == ATAG_HWID) {
			setprop_cell(fdt, "/chosen", "linux,hwid",
					atag->u.revision.rev);
		} else if (atag->hdr.tag == ATAG_SKUID) {
			setprop_cell(fdt, "/chosen", "linux,skuid",
					atag->u.revision.rev);
		} else if (atag->hdr.tag == ATAG_HERO_PANEL_TYPE) {
			setprop_cell(fdt, "/chosen", "linux,panel_type",
					atag->u.revision.rev);
		} else if (atag->hdr.tag == ATAG_GS) {
			setprop_cell(fdt, "/chosen", "linux,gs_calibration",
					atag->u.revision.rev);
		} else if (atag->hdr.tag == ATAG_REVISION) {
			__u32 revision[2];
			revision[0] = cpu_to_fdt32(atag->u.revision.rev);
			revision[1] = cpu_to_fdt32(atag->u.revision.rev);
			if (atag->hdr.size > 3) {
				revision[1] = cpu_to_fdt32(atag->u.revision.rev2);
			}
			setprop_values(fdt, "/chosen", "linux,revision",
					revision, sizeof(revision));
		} else if (atag->hdr.tag == ATAG_PS) {
			__u32 ps_settings[2];
			ps_settings[0] = cpu_to_fdt32(atag->u.serialnr.low);
			ps_settings[1] = cpu_to_fdt32(atag->u.serialnr.high);
			setprop_values(fdt, "/chosen", "linux,ps_calibration",
					ps_settings, sizeof(ps_settings));
		} else if (atag->hdr.tag == ATAG_PS_TYPE) {
			setprop_cell(fdt, "/chosen", "linux,ps_type",
					atag->u.revision.rev);
		}
	}

	if (memcount) {
		setprop(fdt, "/memory", "reg", mem_reg_property,
			4 * memcount * memsize);
	}

	return fdt_pack(fdt);
}