/* * * Copyright (C) 2013 Google, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include <cbfs.h> #include <cbfs_ram.h> #include <string.h> #include <stdio.h> #include <stdlib.h> // Implementation of a media source based on given memory buffer. struct ram_media { char *start; size_t size; }; static int ram_open(struct cbfs_media *media) { return 0; } static void *ram_map(struct cbfs_media *media, size_t offset, size_t count) { struct ram_media *m = (struct ram_media*)media->context; /* assume addressing from top of image in this case */ if (offset > 0xf0000000) { offset = m->size + offset; } if (offset + count > m->size) { printf("ERROR: ram_map: request out of range (0x%zx+0x%zx)\n", offset, count); return CBFS_MEDIA_INVALID_MAP_ADDRESS; } return (void*)(m->start + offset); } static void *ram_unmap(struct cbfs_media *media, const void *address) { return NULL; } static size_t ram_read(struct cbfs_media *media, void *dest, size_t offset, size_t count) { void *ptr = ram_map(media, offset, count); if (ptr == CBFS_MEDIA_INVALID_MAP_ADDRESS) return 0; memcpy(dest, ptr, count); ram_unmap(media, ptr); return count; } static int ram_close(struct cbfs_media *media) { return 0; } int init_cbfs_ram_media(struct cbfs_media *media, void *start, size_t size) { // TODO Find a way to release unused media. Maybe adding media->destroy. struct ram_media *m = (struct ram_media*)malloc(sizeof(*m)); m->start = start; m->size = size; media->context = (void*)m; media->open = ram_open; media->close = ram_close; media->map = ram_map; media->unmap = ram_unmap; media->read = ram_read; return 0; } // Legacy setup_cbfs_from_*. static int is_default_cbfs_media_initialized; static struct cbfs_media default_cbfs_media; int setup_cbfs_from_ram(void *start, uint32_t size) { int result = init_cbfs_ram_media(&default_cbfs_media, start, size); if (result == 0) is_default_cbfs_media_initialized = 1; return result; } extern int libpayload_init_default_cbfs_media(struct cbfs_media *media); int setup_cbfs_from_flash(void) { int result = libpayload_init_default_cbfs_media(&default_cbfs_media); if (result == 0) is_default_cbfs_media_initialized = 1; return result; } int init_default_cbfs_media(struct cbfs_media *media) { int result = 0; if (is_default_cbfs_media_initialized != 1) { result = setup_cbfs_from_flash(); } if (result == 0) memcpy(media, &default_cbfs_media, sizeof(*media)); return result; }