⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 os-area.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 2 页
字号:
		&& i->match_id.key != (int)i->idx->key)		goto next;	return 1;}static int db_delete_64(struct os_area_db *db, const struct os_area_db_id *id){	struct db_iterator i;	for (i.db = NULL; db_for_each_64(db, id, &i); ) {		pr_debug("%s:%d: got (%d:%d) %llxh\n", __func__, __LINE__,			i.idx->owner, i.idx->key,			(unsigned long long)*i.value_64);		i.idx->owner = 0;		i.idx->key = 0;		*i.value_64 = 0;	}	return 0;}static int db_set_64(struct os_area_db *db, const struct os_area_db_id *id,	uint64_t value){	struct db_iterator i;	pr_debug("%s:%d: (%d:%d) <= %llxh\n", __func__, __LINE__,		id->owner, id->key, (unsigned long long)value);	if (!id->owner || id->owner == OS_AREA_DB_OWNER_ANY		|| id->key == OS_AREA_DB_KEY_ANY) {		pr_debug("%s:%d: bad id: (%d:%d)\n", __func__,			__LINE__, id->owner, id->key);		return -1;	}	db_delete_64(db, id);	i.db = NULL;	if (db_for_each_64(db, &os_area_db_id_empty, &i)) {		pr_debug("%s:%d: got (%d:%d) %llxh\n", __func__, __LINE__,			i.idx->owner, i.idx->key,			(unsigned long long)*i.value_64);		i.idx->owner = id->owner;		i.idx->key = id->key;		*i.value_64 = value;		pr_debug("%s:%d: set (%d:%d) <= %llxh\n", __func__, __LINE__,			i.idx->owner, i.idx->key,			(unsigned long long)*i.value_64);		return 0;	}	pr_debug("%s:%d: database full.\n",		__func__, __LINE__);	return -1;}static int db_get_64(const struct os_area_db *db,	const struct os_area_db_id *id, uint64_t *value){	struct db_iterator i;	i.db = NULL;	if (db_for_each_64(db, id, &i)) {		*value = *i.value_64;		pr_debug("%s:%d: found %lld\n", __func__, __LINE__,				(long long int)*i.value_64);		return 0;	}	pr_debug("%s:%d: not found\n", __func__, __LINE__);	return -1;}static int db_get_rtc_diff(const struct os_area_db *db, int64_t *rtc_diff){	return db_get_64(db, &os_area_db_id_rtc_diff, (uint64_t*)rtc_diff);}#define dump_db(a) _dump_db(a, __func__, __LINE__)static void _dump_db(const struct os_area_db *db, const char *func,	int line){	char str[sizeof(db->magic_num) + 1];	dump_field(str, db->magic_num, sizeof(db->magic_num));	pr_debug("%s:%d: db.magic_num:      '%s'\n", func, line,		str);	pr_debug("%s:%d: db.version:         %u\n", func, line,		db->version);	pr_debug("%s:%d: db.index_64:        %u\n", func, line,		db->index_64);	pr_debug("%s:%d: db.count_64:        %u\n", func, line,		db->count_64);	pr_debug("%s:%d: db.index_32:        %u\n", func, line,		db->index_32);	pr_debug("%s:%d: db.count_32:        %u\n", func, line,		db->count_32);	pr_debug("%s:%d: db.index_16:        %u\n", func, line,		db->index_16);	pr_debug("%s:%d: db.count_16:        %u\n", func, line,		db->count_16);}static void os_area_db_init(struct os_area_db *db){	enum {		HEADER_SIZE = offsetof(struct os_area_db, _db_data),		INDEX_64_COUNT = 64,		VALUES_64_COUNT = 57,		INDEX_32_COUNT = 64,		VALUES_32_COUNT = 57,		INDEX_16_COUNT = 64,		VALUES_16_COUNT = 57,	};	memset(db, 0, sizeof(struct os_area_db));	memcpy(db->magic_num, OS_AREA_DB_MAGIC_NUM, sizeof(db->magic_num));	db->version = 1;	db->index_64 = HEADER_SIZE;	db->count_64 = VALUES_64_COUNT;	db->index_32 = HEADER_SIZE			+ INDEX_64_COUNT * sizeof(struct db_index)			+ VALUES_64_COUNT * sizeof(u64);	db->count_32 = VALUES_32_COUNT;	db->index_16 = HEADER_SIZE			+ INDEX_64_COUNT * sizeof(struct db_index)			+ VALUES_64_COUNT * sizeof(u64)			+ INDEX_32_COUNT * sizeof(struct db_index)			+ VALUES_32_COUNT * sizeof(u32);	db->count_16 = VALUES_16_COUNT;	/* Rules to check db layout. */	BUILD_BUG_ON(sizeof(struct db_index) != 1);	BUILD_BUG_ON(sizeof(struct os_area_db) != 2 * OS_AREA_SEGMENT_SIZE);	BUILD_BUG_ON(INDEX_64_COUNT & 0x7);	BUILD_BUG_ON(VALUES_64_COUNT > INDEX_64_COUNT);	BUILD_BUG_ON(INDEX_32_COUNT & 0x7);	BUILD_BUG_ON(VALUES_32_COUNT > INDEX_32_COUNT);	BUILD_BUG_ON(INDEX_16_COUNT & 0x7);	BUILD_BUG_ON(VALUES_16_COUNT > INDEX_16_COUNT);	BUILD_BUG_ON(HEADER_SIZE			+ INDEX_64_COUNT * sizeof(struct db_index)			+ VALUES_64_COUNT * sizeof(u64)			+ INDEX_32_COUNT * sizeof(struct db_index)			+ VALUES_32_COUNT * sizeof(u32)			+ INDEX_16_COUNT * sizeof(struct db_index)			+ VALUES_16_COUNT * sizeof(u16)			> sizeof(struct os_area_db));}/** * update_flash_db - Helper for os_area_queue_work_handler. * */static void update_flash_db(void){	int result;	int file;	off_t offset;	ssize_t count;	static const unsigned int buf_len = 8 * OS_AREA_SEGMENT_SIZE;	const struct os_area_header *header;	struct os_area_db* db;	/* Read in header and db from flash. */	file = sys_open("/dev/ps3flash", O_RDWR, 0);	if (file < 0) {		pr_debug("%s:%d sys_open failed\n", __func__, __LINE__);		goto fail_open;	}	header = kmalloc(buf_len, GFP_KERNEL);	if (!header) {		pr_debug("%s:%d kmalloc failed\n", __func__, __LINE__);		goto fail_malloc;	}	offset = sys_lseek(file, 0, SEEK_SET);	if (offset != 0) {		pr_debug("%s:%d sys_lseek failed\n", __func__, __LINE__);		goto fail_header_seek;	}	count = sys_read(file, (char __user *)header, buf_len);	result = count < OS_AREA_SEGMENT_SIZE || verify_header(header)		|| count < header->db_area_offset * OS_AREA_SEGMENT_SIZE;	if (result) {		pr_debug("%s:%d verify_header failed\n", __func__, __LINE__);		dump_header(header);		goto fail_header;	}	/* Now got a good db offset and some maybe good db data. */	db = (void*)header + header->db_area_offset * OS_AREA_SEGMENT_SIZE;	result = db_verify(db);	if (result) {		printk(KERN_NOTICE "%s:%d: Verify of flash database failed, "			"formatting.\n", __func__, __LINE__);		dump_db(db);		os_area_db_init(db);	}	/* Now got good db data. */	db_set_64(db, &os_area_db_id_rtc_diff, saved_params.rtc_diff);	offset = sys_lseek(file, header->db_area_offset * OS_AREA_SEGMENT_SIZE,		SEEK_SET);	if (offset != header->db_area_offset * OS_AREA_SEGMENT_SIZE) {		pr_debug("%s:%d sys_lseek failed\n", __func__, __LINE__);		goto fail_db_seek;	}	count = sys_write(file, (const char __user *)db,		sizeof(struct os_area_db));	if (count < sizeof(struct os_area_db)) {		pr_debug("%s:%d sys_write failed\n", __func__, __LINE__);	}fail_db_seek:fail_header:fail_header_seek:	kfree(header);fail_malloc:	sys_close(file);fail_open:	return;}/** * os_area_queue_work_handler - Asynchronous write handler. * * An asynchronous write for flash memory and the device tree.  Do not * call directly, use os_area_queue_work(). */static void os_area_queue_work_handler(struct work_struct *work){	struct device_node *node;	pr_debug(" -> %s:%d\n", __func__, __LINE__);	node = of_find_node_by_path("/");	if (node) {		os_area_set_property(node, &property_rtc_diff);		of_node_put(node);	} else		pr_debug("%s:%d of_find_node_by_path failed\n",			__func__, __LINE__);#if defined(CONFIG_PS3_FLASH) || defined(CONFIG_PS3_FLASH_MODULE)	update_flash_db();#else	printk(KERN_WARNING "%s:%d: No flash rom driver configured.\n",		__func__, __LINE__);#endif	pr_debug(" <- %s:%d\n", __func__, __LINE__);}static void os_area_queue_work(void){	static DECLARE_WORK(q, os_area_queue_work_handler);	wmb();	schedule_work(&q);}/** * ps3_os_area_save_params - Copy data from os area mirror to @saved_params. * * For the convenience of the guest the HV makes a copy of the os area in * flash to a high address in the boot memory region and then puts that RAM * address and the byte count into the repository for retrieval by the guest. * We copy the data we want into a static variable and allow the memory setup * by the HV to be claimed by the lmb manager. * * The os area mirror will not be available to a second stage kernel, and * the header verify will fail.  In this case, the saved_params values will * be set from flash memory or the passed in device tree in ps3_os_area_init(). */void __init ps3_os_area_save_params(void){	int result;	u64 lpar_addr;	unsigned int size;	struct os_area_header *header;	struct os_area_params *params;	struct os_area_db *db;	pr_debug(" -> %s:%d\n", __func__, __LINE__);	result = ps3_repository_read_boot_dat_info(&lpar_addr, &size);	if (result) {		pr_debug("%s:%d ps3_repository_read_boot_dat_info failed\n",			__func__, __LINE__);		return;	}	header = (struct os_area_header *)__va(lpar_addr);	params = (struct os_area_params *)__va(lpar_addr		+ OS_AREA_SEGMENT_SIZE);	result = verify_header(header);	if (result) {		/* Second stage kernels exit here. */		pr_debug("%s:%d verify_header failed\n", __func__, __LINE__);		dump_header(header);		return;	}	db = (struct os_area_db *)__va(lpar_addr		+ header->db_area_offset * OS_AREA_SEGMENT_SIZE);	dump_header(header);	dump_params(params);	dump_db(db);	result = db_verify(db) || db_get_rtc_diff(db, &saved_params.rtc_diff);	if (result)		saved_params.rtc_diff = params->rtc_diff ? params->rtc_diff			: SECONDS_FROM_1970_TO_2000;	saved_params.av_multi_out = params->av_multi_out;	saved_params.valid = 1;	memset(header, 0, sizeof(*header));	pr_debug(" <- %s:%d\n", __func__, __LINE__);}/** * ps3_os_area_init - Setup os area device tree properties as needed. */void __init ps3_os_area_init(void){	struct device_node *node;	pr_debug(" -> %s:%d\n", __func__, __LINE__);	node = of_find_node_by_path("/");	if (!saved_params.valid && node) {		/* Second stage kernels should have a dt entry. */		os_area_get_property(node, &property_rtc_diff);		os_area_get_property(node, &property_av_multi_out);	}	if(!saved_params.rtc_diff)		saved_params.rtc_diff = SECONDS_FROM_1970_TO_2000;	if (node) {		os_area_set_property(node, &property_rtc_diff);		os_area_set_property(node, &property_av_multi_out);		of_node_put(node);	} else		pr_debug("%s:%d of_find_node_by_path failed\n",			__func__, __LINE__);	pr_debug(" <- %s:%d\n", __func__, __LINE__);}/** * ps3_os_area_get_rtc_diff - Returns the rtc diff value. */u64 ps3_os_area_get_rtc_diff(void){	return saved_params.rtc_diff;}/** * ps3_os_area_set_rtc_diff - Set the rtc diff value. * * An asynchronous write is needed to support writing updates from * the timer interrupt context. */void ps3_os_area_set_rtc_diff(u64 rtc_diff){	if (saved_params.rtc_diff != rtc_diff) {		saved_params.rtc_diff = rtc_diff;		os_area_queue_work();	}}/** * ps3_os_area_get_av_multi_out - Returns the default video mode. */enum ps3_param_av_multi_out ps3_os_area_get_av_multi_out(void){    return saved_params.av_multi_out;}EXPORT_SYMBOL_GPL(ps3_os_area_get_av_multi_out);

⌨️ 快捷键说明

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