Changeset View
Changeset View
Standalone View
Standalone View
sys/geom/geom_flashmap.c
/*- | /*- | ||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD | |||||
* | |||||
* Copyright (c) 2012 Semihalf | * Copyright (c) 2012 Semihalf | ||||
* Copyright (c) 2009 Jakub Klama <jakub.klama@uj.edu.pl> | * Copyright (c) 2009 Jakub Klama <jakub.klama@uj.edu.pl> | ||||
* All rights reserved. | * All rights reserved. | ||||
* | * | ||||
* Redistribution and use in source and binary forms, with or without | * Redistribution and use in source and binary forms, with or without | ||||
* modification, are permitted provided that the following conditions | * modification, are permitted provided that the following conditions | ||||
* are met: | * are met: | ||||
* 1. Redistributions of source code must retain the above copyright | * 1. Redistributions of source code must retain the above copyright | ||||
Show All 29 Lines | |||||
#include <geom/geom.h> | #include <geom/geom.h> | ||||
#include <geom/geom_slice.h> | #include <geom/geom_slice.h> | ||||
#include <geom/geom_disk.h> | #include <geom/geom_disk.h> | ||||
#include <dev/nand/nand_dev.h> | #include <dev/nand/nand_dev.h> | ||||
#define FLASHMAP_CLASS_NAME "Flashmap" | #define FLASHMAP_CLASS_NAME "Flashmap" | ||||
#define FLASHMAP_UBOOTHDRSIZE 64 | |||||
#define FLASHMAP_SECTORSIZE (64 * 1024) | |||||
#define FLASHMAP_MARKER_STR "#!/bin/sh" | |||||
struct g_flashmap_slice { | struct g_flashmap_slice { | ||||
off_t sl_start; | off_t sl_start; | ||||
off_t sl_end; | off_t sl_end; | ||||
const char *sl_name; | const char *sl_name; | ||||
STAILQ_ENTRY(g_flashmap_slice) sl_link; | STAILQ_ENTRY(g_flashmap_slice) sl_link; | ||||
}; | }; | ||||
STAILQ_HEAD(g_flashmap_head, g_flashmap_slice); | STAILQ_HEAD(g_flashmap_head, g_flashmap_slice); | ||||
static struct { | static struct { | ||||
const char *type; | const char *type; | ||||
flash_slicer_t slicer; | flash_slicer_t slicer; | ||||
} g_flashmap_slicers[] = { | } g_flashmap_slicers[] = { | ||||
{ "NAND::device", NULL }, | { "NAND::device", NULL }, | ||||
{ "CFI::device", NULL }, | { "CFI::device", NULL }, | ||||
{ "SPI::device", NULL }, | { "SPI::device", NULL }, | ||||
{ "MMC::device", NULL } | { "MMC::device", NULL } | ||||
}; | }; | ||||
static g_ioctl_t g_flashmap_ioctl; | static g_ioctl_t g_flashmap_ioctl; | ||||
static g_taste_t g_flashmap_taste; | static g_taste_t g_flashmap_taste; | ||||
static int g_flashmap_load(device_t dev, struct g_provider *pp, | static int g_flashmap_load(device_t dev, struct g_provider *pp, | ||||
flash_slicer_t slicer, struct g_flashmap_head *head); | struct g_consumer *cp, flash_slicer_t slicer, struct g_flashmap_head *head); | ||||
static int g_flashmap_modify(struct g_geom *gp, const char *devname, | static int g_flashmap_modify(struct g_geom *gp, const char *devname, | ||||
int secsize, struct g_flashmap_head *slices); | int secsize, struct g_flashmap_head *slices); | ||||
static void g_flashmap_print(struct g_flashmap_slice *slice); | static void g_flashmap_print(struct g_flashmap_slice *slice); | ||||
static off_t chkuboothdr(struct g_consumer *cp, off_t offset); | |||||
MALLOC_DECLARE(M_FLASHMAP); | MALLOC_DECLARE(M_FLASHMAP); | ||||
MALLOC_DEFINE(M_FLASHMAP, "geom_flashmap", "GEOM flash memory slicer class"); | MALLOC_DEFINE(M_FLASHMAP, "geom_flashmap", "GEOM flash memory slicer class"); | ||||
static void | static void | ||||
g_flashmap_print(struct g_flashmap_slice *slice) | g_flashmap_print(struct g_flashmap_slice *slice) | ||||
{ | { | ||||
printf("%08jx-%08jx: %s (%juKB)\n", (uintmax_t)slice->sl_start, | printf("%08jx-%08jx: %s (%juKB)\n", (uintmax_t)slice->sl_start, | ||||
▲ Show 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | for (i = 0; i < nitems(g_flashmap_slicers); i++) { | ||||
&size, &dev) == 0) { | &size, &dev) == 0) { | ||||
slicer = g_flashmap_slicers[i].slicer; | slicer = g_flashmap_slicers[i].slicer; | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
if (slicer == NULL) | if (slicer == NULL) | ||||
break; | break; | ||||
if (g_flashmap_load(dev, pp, slicer, &head) == 0) | if (g_flashmap_load(dev, pp, cp, slicer, &head) == 0) | ||||
break; | break; | ||||
g_flashmap_modify(gp, cp->provider->name, | g_flashmap_modify(gp, cp->provider->name, | ||||
cp->provider->sectorsize, &head); | cp->provider->sectorsize, &head); | ||||
} while (0); | } while (0); | ||||
g_access(cp, -1, 0, 0); | g_access(cp, -1, 0, 0); | ||||
STAILQ_FOREACH_SAFE(slice, &head, sl_link, slice_temp) | STAILQ_FOREACH_SAFE(slice, &head, sl_link, slice_temp) | ||||
free(slice, M_FLASHMAP); | free(slice, M_FLASHMAP); | ||||
if (LIST_EMPTY(&gp->provider)) { | if (LIST_EMPTY(&gp->provider)) { | ||||
g_slice_spoiled(cp); | g_slice_spoiled(cp); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
return (gp); | return (gp); | ||||
} | } | ||||
static off_t | |||||
chkuboothdr(struct g_consumer *cp, off_t offset) | |||||
{ | |||||
off_t val; | |||||
mizhka: add declaration at top of file? | |||||
uint8_t *buf; | |||||
size_t sectorsize; | |||||
int i; | |||||
Not Done Inline Actions128 bytes on stack is not good, please malloc/free it. mizhka: 128 bytes on stack is not good, please malloc/free it. | |||||
sectorsize = FLASHMAP_SECTORSIZE; | |||||
sectorsize = cp->provider->sectorsize; | |||||
buf = g_read_data(cp, offset, sectorsize, NULL); | |||||
/* check u-boot header magic number */ | |||||
if (buf[0] != 0x27 || buf[1] != 0x05 || buf[2] != 0x19 || | |||||
buf[3] != 0x56) { | |||||
g_free(buf); | |||||
return 0; | |||||
} | |||||
/* get image data size */ | |||||
val = buf[0xc] << 24 | buf[0xd] << 16 | buf[0xe] << 8 | buf[0xf]; | |||||
val += FLASHMAP_UBOOTHDRSIZE; | |||||
val = (val - 1) / FLASHMAP_SECTORSIZE; | |||||
val = (val + 1) * FLASHMAP_SECTORSIZE; | |||||
g_free(buf); | |||||
/* check 64K and 128K boundly */ | |||||
for (i = 0; i < 2; ++i) { | |||||
buf = g_read_data(cp, offset + val, sectorsize, NULL); | |||||
if (strncmp(buf, FLASHMAP_MARKER_STR, | |||||
strlen(FLASHMAP_MARKER_STR)) == 0) | |||||
break; | |||||
g_free(buf); | |||||
val += FLASHMAP_SECTORSIZE; | |||||
} | |||||
if (i == 2) | |||||
return 0; | |||||
g_free(buf); | |||||
return offset + val; | |||||
} | |||||
static int | static int | ||||
g_flashmap_load(device_t dev, struct g_provider *pp, flash_slicer_t slicer, | g_flashmap_load(device_t dev, struct g_provider *pp, struct g_consumer *cp, | ||||
struct g_flashmap_head *head) | flash_slicer_t slicer, struct g_flashmap_head *head) | ||||
{ | { | ||||
struct flash_slice *slices; | struct flash_slice *slices; | ||||
struct g_flashmap_slice *slice; | struct g_flashmap_slice *slice; | ||||
Not Done Inline Actionsbootverbose? mizhka: bootverbose? | |||||
int i, nslices = 0; | int i, nslices = 0; | ||||
struct g_flashmap_slice *rootfs; | |||||
off_t rootfsbase; | |||||
char *rootfsname; | |||||
Not Done Inline Actionsplease prefix g_flashmap_% mizhka: please prefix g_flashmap_% | |||||
slices = malloc(sizeof(struct flash_slice) * FLASH_SLICES_MAX_NUM, | slices = malloc(sizeof(struct flash_slice) * FLASH_SLICES_MAX_NUM, | ||||
M_FLASHMAP, M_WAITOK | M_ZERO); | M_FLASHMAP, M_WAITOK | M_ZERO); | ||||
if (slicer(dev, pp->name, slices, &nslices) == 0) { | if (slicer(dev, pp->name, slices, &nslices) == 0) { | ||||
for (i = 0; i < nslices; i++) { | for (i = 0; i < nslices; i++) { | ||||
slice = malloc(sizeof(struct g_flashmap_slice), | slice = malloc(sizeof(struct g_flashmap_slice), | ||||
M_FLASHMAP, M_WAITOK); | M_FLASHMAP, M_WAITOK); | ||||
slice->sl_name = slices[i].label; | slice->sl_name = slices[i].label; | ||||
slice->sl_start = slices[i].base; | slice->sl_start = slices[i].base; | ||||
slice->sl_end = slices[i].base + slices[i].size - 1; | slice->sl_end = slices[i].base + slices[i].size - 1; | ||||
if(strcmp("firmware", slice->sl_name) == 0) { | |||||
rootfsbase = chkuboothdr(cp, slice->sl_start); | |||||
if (rootfsbase != 0) { | |||||
rootfs = malloc(sizeof( | |||||
struct g_flashmap_slice), | |||||
M_FLASHMAP, M_WAITOK); | |||||
slice->sl_end = rootfsbase - 1; | |||||
rootfsname = g_malloc(32, | |||||
M_WAITOK | M_ZERO); | |||||
strcpy(rootfsname, "rootfs"); | |||||
rootfs->sl_name = rootfsname; | |||||
rootfs->sl_start = rootfsbase; | |||||
rootfs->sl_end = slices[i].base + | |||||
slices[i].size - 1; | |||||
STAILQ_INSERT_TAIL(head, slice, | |||||
sl_link); | |||||
STAILQ_INSERT_TAIL(head, rootfs, | |||||
sl_link); | |||||
} else { | |||||
STAILQ_INSERT_TAIL(head, slice, | |||||
sl_link); | |||||
} | |||||
} else { | |||||
STAILQ_INSERT_TAIL(head, slice, sl_link); | STAILQ_INSERT_TAIL(head, slice, sl_link); | ||||
} | |||||
} | } | ||||
} | } | ||||
free(slices, M_FLASHMAP); | free(slices, M_FLASHMAP); | ||||
return (nslices); | return (nslices); | ||||
} | } | ||||
void flash_register_slicer(flash_slicer_t slicer, u_int type, bool force) | void flash_register_slicer(flash_slicer_t slicer, u_int type, bool force) | ||||
Show All 17 Lines |
add declaration at top of file?