162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *  PS3 bootwrapper support.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci *  Copyright (C) 2007 Sony Computer Entertainment Inc.
662306a36Sopenharmony_ci *  Copyright 2007 Sony Corp.
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <stdarg.h>
1062306a36Sopenharmony_ci#include <stddef.h>
1162306a36Sopenharmony_ci#include "types.h"
1262306a36Sopenharmony_ci#include "elf.h"
1362306a36Sopenharmony_ci#include "string.h"
1462306a36Sopenharmony_ci#include "stdio.h"
1562306a36Sopenharmony_ci#include "page.h"
1662306a36Sopenharmony_ci#include "ops.h"
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ciextern int lv1_panic(u64 in_1);
1962306a36Sopenharmony_ciextern int lv1_get_logical_partition_id(u64 *out_1);
2062306a36Sopenharmony_ciextern int lv1_get_logical_ppe_id(u64 *out_1);
2162306a36Sopenharmony_ciextern int lv1_get_repository_node_value(u64 in_1, u64 in_2, u64 in_3,
2262306a36Sopenharmony_ci	u64 in_4, u64 in_5, u64 *out_1, u64 *out_2);
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ciBSS_STACK(4096);
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci/* A buffer that may be edited by tools operating on a zImage binary so as to
2762306a36Sopenharmony_ci * edit the command line passed to vmlinux (by setting /chosen/bootargs).
2862306a36Sopenharmony_ci * The buffer is put in it's own section so that tools may locate it easier.
2962306a36Sopenharmony_ci */
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_cistatic char cmdline[BOOT_COMMAND_LINE_SIZE]
3262306a36Sopenharmony_ci	__attribute__((__section__("__builtin_cmdline")));
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_cistatic void prep_cmdline(void *chosen)
3562306a36Sopenharmony_ci{
3662306a36Sopenharmony_ci	if (cmdline[0] == '\0')
3762306a36Sopenharmony_ci		getprop(chosen, "bootargs", cmdline, BOOT_COMMAND_LINE_SIZE-1);
3862306a36Sopenharmony_ci	else
3962306a36Sopenharmony_ci		setprop_str(chosen, "bootargs", cmdline);
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	printf("cmdline: '%s'\n", cmdline);
4262306a36Sopenharmony_ci}
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_cistatic void ps3_console_write(const char *buf, int len)
4562306a36Sopenharmony_ci{
4662306a36Sopenharmony_ci}
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_cistatic void ps3_exit(void)
4962306a36Sopenharmony_ci{
5062306a36Sopenharmony_ci	printf("ps3_exit\n");
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	/* lv1_panic will shutdown the lpar. */
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	lv1_panic(0); /* zero = do not reboot */
5562306a36Sopenharmony_ci	while (1);
5662306a36Sopenharmony_ci}
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_cistatic int ps3_repository_read_rm_size(u64 *rm_size)
5962306a36Sopenharmony_ci{
6062306a36Sopenharmony_ci	int result;
6162306a36Sopenharmony_ci	u64 lpar_id;
6262306a36Sopenharmony_ci	u64 ppe_id;
6362306a36Sopenharmony_ci	u64 v2;
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	result = lv1_get_logical_partition_id(&lpar_id);
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	if (result)
6862306a36Sopenharmony_ci		return -1;
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	result = lv1_get_logical_ppe_id(&ppe_id);
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci	if (result)
7362306a36Sopenharmony_ci		return -1;
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci	/*
7662306a36Sopenharmony_ci	 * n1: 0000000062690000 : ....bi..
7762306a36Sopenharmony_ci	 * n2: 7075000000000000 : pu......
7862306a36Sopenharmony_ci	 * n3: 0000000000000001 : ........
7962306a36Sopenharmony_ci	 * n4: 726d5f73697a6500 : rm_size.
8062306a36Sopenharmony_ci	*/
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	result = lv1_get_repository_node_value(lpar_id, 0x0000000062690000ULL,
8362306a36Sopenharmony_ci		0x7075000000000000ULL, ppe_id, 0x726d5f73697a6500ULL, rm_size,
8462306a36Sopenharmony_ci		&v2);
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	printf("%s:%d: ppe_id  %lu \n", __func__, __LINE__,
8762306a36Sopenharmony_ci		(unsigned long)ppe_id);
8862306a36Sopenharmony_ci	printf("%s:%d: lpar_id %lu \n", __func__, __LINE__,
8962306a36Sopenharmony_ci		(unsigned long)lpar_id);
9062306a36Sopenharmony_ci	printf("%s:%d: rm_size %llxh \n", __func__, __LINE__, *rm_size);
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci	return result ? -1 : 0;
9362306a36Sopenharmony_ci}
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_civoid ps3_copy_vectors(void)
9662306a36Sopenharmony_ci{
9762306a36Sopenharmony_ci	extern char __system_reset_kernel[];
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	memcpy((void *)0x100, __system_reset_kernel, 512);
10062306a36Sopenharmony_ci	flush_cache((void *)0x100, 512);
10162306a36Sopenharmony_ci}
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_civoid platform_init(void)
10462306a36Sopenharmony_ci{
10562306a36Sopenharmony_ci	const u32 heapsize = 0x1000000 - (u32)_end; /* 16MiB */
10662306a36Sopenharmony_ci	void *chosen;
10762306a36Sopenharmony_ci	unsigned long ft_addr;
10862306a36Sopenharmony_ci	u64 rm_size;
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci	console_ops.write = ps3_console_write;
11162306a36Sopenharmony_ci	platform_ops.exit = ps3_exit;
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci	printf("\n-- PS3 bootwrapper --\n");
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci	simple_alloc_init(_end, heapsize, 32, 64);
11662306a36Sopenharmony_ci	fdt_init(_dtb_start);
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	chosen = finddevice("/chosen");
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	ps3_repository_read_rm_size(&rm_size);
12162306a36Sopenharmony_ci	dt_fixup_memory(0, rm_size);
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci	if (&_initrd_end > &_initrd_start) {
12462306a36Sopenharmony_ci		setprop_val(chosen, "linux,initrd-start", (u32)(_initrd_start));
12562306a36Sopenharmony_ci		setprop_val(chosen, "linux,initrd-end", (u32)(_initrd_end));
12662306a36Sopenharmony_ci	}
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci	prep_cmdline(chosen);
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci	ft_addr = dt_ops.finalize();
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci	ps3_copy_vectors();
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci	printf(" flat tree at 0x%lx\n\r", ft_addr);
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci	((kernel_entry_t)0)(ft_addr, 0, NULL);
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	ps3_exit();
13962306a36Sopenharmony_ci}
140