Ejemplo n.º 1
0
static int open_partition(const char *name)
{
    uint32_t index;
    int rc;

    /* Open libffs if needed */
    if (!ffsh) {
        rc = ffs_init(ffs_toc, fl_total_size, bl, &ffsh, 0);
        if (rc) {
            fprintf(stderr, "Error %d opening ffs !\n", rc);
            if (ffs_toc)
                fprintf(stderr, "You specified 0x%08x as the libffs TOC"
                        " looks like it doesn't exist\n", ffs_toc);
            return rc;
        }
    }

    /* Find partition */
    rc = ffs_lookup_part(ffsh, name, &index);
    if (rc == FFS_ERR_PART_NOT_FOUND) {
        fprintf(stderr, "Partition '%s' not found !\n", name);
        return rc;
    }
    if (rc) {
        fprintf(stderr, "Error %d looking for partition '%s' !\n",
                rc, name);
        return rc;
    }

    ffs_index = index;
    return 0;
}
Ejemplo n.º 2
0
int flash_register(struct blocklevel_device *bl)
{
	uint64_t size;
	uint32_t block_size;
	struct ffs_handle *ffs;
	struct dt_node *node;
	struct flash *flash;
	const char *name;
	int rc;

	rc = blocklevel_get_info(bl, &name, &size, &block_size);
	if (rc)
		return rc;

	if (!name)
		name = "(unnamed)";

	prlog(PR_INFO, "FLASH: registering flash device %s "
			"(size 0x%llx, blocksize 0x%x)\n",
			name, size, block_size);

	flash = malloc(sizeof(struct flash));
	if (!flash) {
		prlog(PR_ERR, "FLASH: Error allocating flash structure\n");
		return OPAL_RESOURCE;
	}

	flash->busy = false;
	flash->bl = bl;
	flash->no_erase = !(bl->flags & WRITE_NEED_ERASE);
	flash->size = size;
	flash->block_size = block_size;
	flash->id = num_flashes();

	rc = ffs_init(0, flash->size, bl, &ffs, 1);
	if (rc) {
		/**
		 * @fwts-label NoFFS
		 * @fwts-advice System flash isn't formatted as expected.
		 * This could mean several OPAL utilities do not function
		 * as expected. e.g. gard, pflash.
		 */
		prlog(PR_WARNING, "FLASH: No ffs info; "
				"using raw device only\n");
		ffs = NULL;
	}

	node = flash_add_dt_node(flash, flash->id);

	setup_system_flash(flash, node, name, ffs);

	if (ffs)
		ffs_close(ffs);

	lock(&flash_lock);
	list_add(&flashes, &flash->list);
	unlock(&flash_lock);

	return OPAL_SUCCESS;
}
Ejemplo n.º 3
0
/*
 * Memory based filesystem initialization.
 */
void
mfs_init(void)
{

	if (mfs_initcnt++ == 0) {
		mutex_init(&mfs_lock, MUTEX_DEFAULT, IPL_NONE);
		ffs_init();
	}
}
Ejemplo n.º 4
0
static void print_ffs_info(uint32_t toc_offset)
{
    struct ffs_handle *ffs_handle;
    uint32_t other_side_offset = 0;
    int rc;
    uint32_t i;

    rc = ffs_init(toc_offset, fl_total_size, bl, &ffs_handle, 0);
    if (rc) {
        fprintf(stderr, "Error %d opening ffs !\n", rc);
        return;
    }

    printf("\n");
    printf("TOC@0x%08x Partitions:\n", toc_offset);
    printf("-----------\n");

    for (i = 0;; i++) {
        uint32_t start, size, act, end;
        bool ecc;
        char *name;

        rc = ffs_part_info(ffs_handle, i, &name, &start, &size, &act, &ecc);
        if (rc == FFS_ERR_PART_NOT_FOUND)
            break;
        if (rc) {
            fprintf(stderr, "Error %d scanning partitions\n", rc);
            break;
        }
        end = start + size;
        printf("ID=%02d %15s %08x..%08x (actual=%08x) %s\n",
               i, name, start, end, act, ecc ? "[ECC]" : "");

        if (strcmp(name, "OTHER_SIDE") == 0)
            other_side_offset = start;

        free(name);
    }

    ffs_close(ffs_handle);

    if (other_side_offset)
        print_ffs_info(other_side_offset);
}
Ejemplo n.º 5
0
int ffs_next_side(struct ffs_handle *ffs, struct ffs_handle **new_ffs,
		bool mark_ecc)
{
	int rc;
	uint32_t index, offset, max_size;

	if (!ffs || !new_ffs)
		return FLASH_ERR_PARM_ERROR;

	*new_ffs = NULL;

	rc = ffs_lookup_part(ffs, "OTHER_SIDE", &index);
	if (rc)
		return rc;

	rc = ffs_part_info(ffs, index, NULL, &offset, &max_size, NULL, NULL);
	if (rc)
		return rc;

	return ffs_init(offset, max_size, ffs->bl, new_ffs, mark_ecc);
}
Ejemplo n.º 6
0
/*! initialize thread structures and create idle thread */
void kthreads_init ()
{
	extern kprog_t prog;
	int prio;

	list_init ( &all_threads );

	active_thread = NULL;
	ksched_init ();

	/* initially create 'idle thread' */
	kernel_proc.prog = NULL;
	kernel_proc.stack_pool = NULL; /* use kernel pool */
	kernel_proc.m.start = NULL;
	kernel_proc.m.size = (size_t) 0xffffffff;

	(void) kthread_create ( idle_thread, NULL, 0, SCHED_FIFO, 0, NULL,
				NULL, 0, &kernel_proc );

	/* user_proc */
	user_proc.prog = &prog;
	user_proc.m.size = prog.m->size;
	user_proc.m.start = user_proc.pi = prog.pi;

	/* initialize memory pool for threads stacks */
	user_proc.stack_pool = ffs_init (
		U2K_GET_ADR ( user_proc.pi->stack, &user_proc ),
		(size_t) prog.pi->end_adr - (size_t) prog.pi->stack + 1 );

	prio = prog.pi->prio;
	if ( !prio )
		prio = THREAD_DEF_PRIO;

	kthread_create ( user_proc.pi->init, NULL, 0, SCHED_FIFO, prio, NULL,
			 NULL, 0, &user_proc );

	kthreads_schedule ();
}
Ejemplo n.º 7
0
/*
 * Memory based filesystem initialization.
 */
int
mfs_init(struct vfsconf *vfsp)
{
	return (ffs_init(vfsp));
}
Ejemplo n.º 8
0
/*
 * load a resource from FLASH
 * buf and len shouldn't account for ECC even if partition is ECCed.
 *
 * The API here is a bit strange.
 * If resource has a STB container, buf will contain it
 * If loading subpartition with STB container, buff will *NOT* contain it
 * For trusted boot, the whole partition containing the subpart is measured.
 *
 * Additionally, the logic to work out how much to read from flash is insane.
 */
static int flash_load_resource(enum resource_id id, uint32_t subid,
			       void *buf, size_t *len)
{
	int i;
	int rc = OPAL_RESOURCE;
	struct ffs_handle *ffs;
	struct flash *flash;
	const char *name;
	bool status = false;
	bool ecc;
	bool part_signed = false;
	void *bufp = buf;
	size_t bufsz = *len;
	int ffs_part_num, ffs_part_start, ffs_part_size;
	int content_size = 0;
	int offset = 0;

	lock(&flash_lock);

	if (!system_flash) {
		/**
		 * @fwts-label SystemFlashNotFound
		 * @fwts-advice No system flash was found. Check for missing
		 * calls flash_register(...).
		 */
		prlog(PR_WARNING, "FLASH: Can't load resource id:%i. "
		      "No system flash found\n", id);
		goto out_unlock;
	}

	flash = system_flash;

	if (flash->busy)
		goto out_unlock;

	for (i = 0, name = NULL; i < ARRAY_SIZE(part_name_map); i++) {
		if (part_name_map[i].id == id) {
			name = part_name_map[i].name;
			break;
		}
	}
	if (!name) {
		prerror("FLASH: Couldn't find partition for id %d\n", id);
		goto out_unlock;
	}
	/*
	 * If partition doesn't have a subindex but the caller specifies one,
	 * we fail.  eg. kernel partition doesn't have a subindex
	 */
	if ((part_name_map[i].subid == RESOURCE_SUBID_NONE) &&
	    (subid != RESOURCE_SUBID_NONE)) {
		prerror("PLAT: Partition %s doesn't have subindex\n", name);
		goto out_unlock;
	}

	rc = ffs_init(0, flash->size, flash->bl, &ffs, 1);
	if (rc) {
		prerror("FLASH: Can't open ffs handle: %d\n", rc);
		goto out_unlock;
	}

	rc = ffs_lookup_part(ffs, name, &ffs_part_num);
	if (rc) {
		/* This is not an error per-se, some partitions
		 * are purposefully absent, don't spam the logs
		 */
	        prlog(PR_DEBUG, "FLASH: No %s partition\n", name);
		goto out_free_ffs;
	}
	rc = ffs_part_info(ffs, ffs_part_num, NULL,
			   &ffs_part_start, NULL, &ffs_part_size, &ecc);
	if (rc) {
		prerror("FLASH: Failed to get %s partition info\n", name);
		goto out_free_ffs;
	}
	prlog(PR_DEBUG,"FLASH: %s partition %s ECC\n",
	      name, ecc  ? "has" : "doesn't have");

	if (ffs_part_size < SECURE_BOOT_HEADERS_SIZE) {
		prerror("FLASH: secboot headers bigger than "
			"partition size 0x%x\n", ffs_part_size);
		goto out_free_ffs;
	}

	rc = blocklevel_read(flash->bl, ffs_part_start, bufp,
			SECURE_BOOT_HEADERS_SIZE);
	if (rc) {
		prerror("FLASH: failed to read the first 0x%x from "
			"%s partition, rc %d\n", SECURE_BOOT_HEADERS_SIZE,
			name, rc);
		goto out_free_ffs;
	}

	part_signed = stb_is_container(bufp, SECURE_BOOT_HEADERS_SIZE);

	prlog(PR_DEBUG, "FLASH: %s partition %s signed\n", name,
	      part_signed ? "is" : "isn't");

	/*
	 * part_start/size are raw pointers into the partition.
	 *  ie. they will account for ECC if included.
	 */

	if (part_signed) {
		bufp += SECURE_BOOT_HEADERS_SIZE;
		bufsz -= SECURE_BOOT_HEADERS_SIZE;
		content_size = stb_sw_payload_size(buf, SECURE_BOOT_HEADERS_SIZE);
		*len = content_size + SECURE_BOOT_HEADERS_SIZE;

		if (content_size > bufsz) {
			prerror("FLASH: content size > buffer size\n");
			rc = OPAL_PARAMETER;
			goto out_free_ffs;
		}

		ffs_part_start += SECURE_BOOT_HEADERS_SIZE;

		rc = blocklevel_read(flash->bl, ffs_part_start, bufp,
					  content_size);
		if (rc) {
			prerror("FLASH: failed to read content size %d"
				" %s partition, rc %d\n",
				content_size, name, rc);
			goto out_free_ffs;
		}

		if (subid == RESOURCE_SUBID_NONE)
			goto done_reading;

		rc = flash_subpart_info(bufp, content_size, ffs_part_size,
					NULL, subid, &offset, &content_size);
		if (rc) {
			prerror("FLASH: Failed to parse subpart info for %s\n",
				name);
			goto out_free_ffs;
		}
		bufp += offset;
		goto done_reading;
	} else /* stb_signed */ {
		/*
		 * Back to the old way of doing things, no STB header.
		 */
		if (subid == RESOURCE_SUBID_NONE) {
			if (id == RESOURCE_ID_KERNEL ||
				id == RESOURCE_ID_INITRAMFS) {
				/*
				 * Because actualSize is a lie, we compute the
				 * size of the BOOTKERNEL based on what the ELF
				 * headers say. Otherwise we end up reading more
				 * than we should
				 */
				content_size = sizeof_elf_from_hdr(buf);
				if (!content_size) {
					prerror("FLASH: Invalid ELF header part"
						" %s\n", name);
					rc = OPAL_RESOURCE;
					goto out_free_ffs;
				}
			} else {
				content_size = ffs_part_size;
			}
			if (content_size > bufsz) {
				prerror("FLASH: %s content size %d > "
					" buffer size %lu\n", name,
					content_size, bufsz);
				rc = OPAL_PARAMETER;
				goto out_free_ffs;
			}
			prlog(PR_DEBUG, "FLASH: computed %s size %u\n",
			      name, content_size);
			rc = blocklevel_read(flash->bl, ffs_part_start,
						  buf, content_size);
			if (rc) {
				prerror("FLASH: failed to read content size %d"
					" %s partition, rc %d\n",
					content_size, name, rc);
				goto out_free_ffs;
			}
			*len = content_size;
			goto done_reading;
		}
		BUILD_ASSERT(FLASH_SUBPART_HEADER_SIZE <= SECURE_BOOT_HEADERS_SIZE);
		rc = flash_subpart_info(bufp, SECURE_BOOT_HEADERS_SIZE,
					ffs_part_size, &ffs_part_size, subid,
					&offset, &content_size);
		if (rc) {
			prerror("FLASH: FAILED reading subpart info. rc=%d\n",
				rc);
			goto out_free_ffs;
		}

		*len = ffs_part_size;
		prlog(PR_DEBUG, "FLASH: Computed %s partition size: %u "
		      "(subpart %u size %u offset %u)\n", name, ffs_part_size,
		      subid, content_size, offset);
		/*
		 * For a sub partition, we read the whole (computed)
		 * partition, and then measure that.
		 * Afterwards, we memmove() things back into place for
		 * the caller.
		 */
		rc = blocklevel_read(flash->bl, ffs_part_start,
					  buf, ffs_part_size);

		bufp += offset;
	}

done_reading:
	/*
	 * Verify and measure the retrieved PNOR partition as part of the
	 * secure boot and trusted boot requirements
	 */
	secureboot_verify(id, buf, *len);
	trustedboot_measure(id, buf, *len);

	/* Find subpartition */
	if (subid != RESOURCE_SUBID_NONE) {
		memmove(buf, bufp, content_size);
		*len = content_size;
	}

	status = true;

out_free_ffs:
	ffs_close(ffs);
out_unlock:
	unlock(&flash_lock);
	return status ? OPAL_SUCCESS : rc;
}
Ejemplo n.º 9
0
static struct dt_node *flash_add_dt_node(struct flash *flash, int id)
{
	int i;
	int rc;
	const char *name;
	bool ecc;
	struct ffs_handle *ffs;
	int ffs_part_num, ffs_part_start, ffs_part_size;
	struct dt_node *flash_node;
	struct dt_node *partition_container_node;
	struct dt_node *partition_node;

	flash_node = dt_new_addr(opal_node, "flash", id);
	dt_add_property_strings(flash_node, "compatible", "ibm,opal-flash");
	dt_add_property_cells(flash_node, "ibm,opal-id", id);
	dt_add_property_u64(flash_node, "reg", flash->size);
	dt_add_property_cells(flash_node, "ibm,flash-block-size",
			flash->block_size);
	if (flash->no_erase)
		dt_add_property(flash_node, "no-erase", NULL, 0);

	/* we fix to 32-bits */
	dt_add_property_cells(flash_node, "#address-cells", 1);
	dt_add_property_cells(flash_node, "#size-cells", 1);

	/* Add partition container node */
	partition_container_node = dt_new(flash_node, "partitions");
	dt_add_property_strings(partition_container_node, "compatible", "fixed-partitions");

	/* we fix to 32-bits */
	dt_add_property_cells(partition_container_node, "#address-cells", 1);
	dt_add_property_cells(partition_container_node, "#size-cells", 1);

	/* Add partitions */
	for (i = 0, name = NULL; i < ARRAY_SIZE(part_name_map); i++) {
		name = part_name_map[i].name;

		rc = ffs_init(0, flash->size, flash->bl, &ffs, 1);
		if (rc) {
			prerror("FLASH: Can't open ffs handle\n");
			continue;
		}

		rc = ffs_lookup_part(ffs, name, &ffs_part_num);
		if (rc) {
			/* This is not an error per-se, some partitions
			 * are purposefully absent, don't spam the logs
			 */
		        prlog(PR_DEBUG, "FLASH: No %s partition\n", name);
			continue;
		}
		rc = ffs_part_info(ffs, ffs_part_num, NULL,
				   &ffs_part_start, NULL, &ffs_part_size, &ecc);
		if (rc) {
			prerror("FLASH: Failed to get %s partition info\n", name);
			continue;
		}

		partition_node = dt_new_addr(partition_container_node, "partition", ffs_part_start);
		dt_add_property_strings(partition_node, "label", name);
		dt_add_property_cells(partition_node, "reg", ffs_part_start, ffs_part_size);
		if (part_name_map[i].id != RESOURCE_ID_KERNEL_FW) {
			/* Mark all partitions other than the full PNOR and the boot kernel
			 * firmware as read only.  These two partitions are the only partitions
			 * that are properly erase block aligned at this time.
			 */
			dt_add_property(partition_node, "read-only", NULL, 0);
		}
	}

	partition_node = dt_new_addr(partition_container_node, "partition", 0);
	dt_add_property_strings(partition_node, "label", "PNOR");
	dt_add_property_cells(partition_node, "reg", 0, flash->size);

	return flash_node;
}
Ejemplo n.º 10
0
/*!
 * Start program defined by 'prog' (loaded as module) as new process:
 * - initialize environment (stack area for threads, stdin, stdout) and start
 *   it's first thread
 * \param prog_name Program name (as given with module)
 * \param param Command line arguments for starting thread (if not NULL)
 * \param prio Priority for starting thread
 * \return Pointer to descriptor of created process
 */
kthread_t *k_proc_start ( char *prog_name, void *param, int prio )
{
	extern kdevice_t *u_stdin, *u_stdout;
	extern list_t progs;
	kprog_t *prog;
	kprocess_t *proc;
	kthread_t *kthr;
	char **args = NULL, *arg, *karg, **kargs;
	size_t argsize;
	int i;

	prog = list_get ( &progs, FIRST );
	while ( prog && strcmp ( prog->prog_name, prog_name ) )
		prog = list_get_next ( &prog->all );

	if ( !prog )
		return NULL;

	if ( prog->started )
		return NULL;

	/* create new process */
	proc = kmalloc ( sizeof ( kprocess_t) );
	ASSERT ( proc );

	proc->prog = prog;
	proc->m.size = prog->m.size;
	proc->m.start = proc->pi = prog->pi;

	proc->pi->stdin = u_stdin;
	proc->pi->stdout = u_stdout;

	/* initialize memory pool for threads stacks */
	proc->stack_pool = ffs_init ( U2K_GET_ADR ( proc->pi->stack, proc ),
				      prog->pi->stack_size );

	proc->thr_count = 0;

	if ( !prio )
		prio = proc->pi->prio;
	if ( !prio )
		prio = THR_DEFAULT_PRIO;

	if ( param ) /* have arguments? */
	{
		/* copy command line arguments from kernel space to process;
		   (use process stack space for arguments) */
		kargs = param;
		for ( i = 0; kargs[i]; i++ ) ;
		argsize = ( (size_t) kargs[i-1] + strlen( kargs[i-1] ) + 1 )
			  - (size_t) param;
		if ( argsize > 0 )
		{
			args = ffs_alloc ( proc->stack_pool, argsize );
			arg = (void *) args + (i + 1) * sizeof (void *);
			kargs = param;
			i = 0;
			do {
				karg = kargs[i];
				strcpy ( arg, karg );
				args[i++] = K2U_GET_ADR ( arg, proc );
				arg += strlen ( arg ) + 1;
			}
			while ( kargs[i] );
			args[i] = NULL;
			args = K2U_GET_ADR ( args, proc );
		}

		kfree ( param );
	}
	kthr = k_create_thread ( proc->pi->init, args, NULL, prio, NULL, 0, 1,
				proc );

	list_append ( &procs, proc, &proc->all );

	prog->started = 1;

	k_schedule_threads ();

	return kthr;
}