Changeset View
Changeset View
Standalone View
Standalone View
head/stand/fdt/fdt_loader_cmd.c
Show First 20 Lines • Show All 68 Lines • ▼ Show 20 Lines | |||||
static size_t fdtp_size = 0; | static size_t fdtp_size = 0; | ||||
/* Location of FDT in kernel or module. */ | /* Location of FDT in kernel or module. */ | ||||
/* This won't be set if FDT is loaded from disk or memory. */ | /* This won't be set if FDT is loaded from disk or memory. */ | ||||
/* If it is set, we'll update it when fdt_copy() gets called. */ | /* If it is set, we'll update it when fdt_copy() gets called. */ | ||||
static vm_offset_t fdtp_va = 0; | static vm_offset_t fdtp_va = 0; | ||||
static int fdt_load_dtb(vm_offset_t va); | static int fdt_load_dtb(vm_offset_t va); | ||||
static void fdt_print_overlay_load_error(int err, const char *filename); | static void fdt_print_overlay_load_error(int err, const char *filename); | ||||
static int fdt_check_overlay_compatible(void *base_fdt, void *overlay_fdt); | |||||
static int fdt_cmd_nyi(int argc, char *argv[]); | static int fdt_cmd_nyi(int argc, char *argv[]); | ||||
static int fdt_load_dtb_overlays_string(const char * filenames); | static int fdt_load_dtb_overlays_string(const char * filenames); | ||||
static int fdt_cmd_addr(int argc, char *argv[]); | static int fdt_cmd_addr(int argc, char *argv[]); | ||||
static int fdt_cmd_mkprop(int argc, char *argv[]); | static int fdt_cmd_mkprop(int argc, char *argv[]); | ||||
static int fdt_cmd_cd(int argc, char *argv[]); | static int fdt_cmd_cd(int argc, char *argv[]); | ||||
static int fdt_cmd_hdr(int argc, char *argv[]); | static int fdt_cmd_hdr(int argc, char *argv[]); | ||||
▲ Show 20 Lines • Show All 284 Lines • ▼ Show 20 Lines | if (err != 0) | ||||
fdt_print_overlay_load_error(err, name); | fdt_print_overlay_load_error(err, name); | ||||
name = comaptr + 1; | name = comaptr + 1; | ||||
} while(comaptr); | } while(comaptr); | ||||
free(names); | free(names); | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | |||||
* fdt_check_overlay_compatible - check that the overlay_fdt is compatible with | |||||
* base_fdt before we attempt to apply it. It will need to re-calculate offsets | |||||
* in the base every time, rather than trying to cache them earlier in the | |||||
* process, because the overlay application process can/will invalidate a lot of | |||||
* offsets. | |||||
*/ | |||||
static int | |||||
fdt_check_overlay_compatible(void *base_fdt, void *overlay_fdt) | |||||
{ | |||||
const char *compat; | |||||
int compat_len, ocompat_len; | |||||
int oroot_offset, root_offset; | |||||
int slidx, sllen; | |||||
oroot_offset = fdt_path_offset(overlay_fdt, "/"); | |||||
if (oroot_offset < 0) | |||||
return (oroot_offset); | |||||
/* | |||||
* If /compatible in the overlay does not exist or if it is empty, then | |||||
* we're automatically compatible. We do this for the sake of rapid | |||||
* overlay development for overlays that aren't intended to be deployed. | |||||
* The user assumes the risk of using an overlay without /compatible. | |||||
*/ | |||||
if (fdt_get_property(overlay_fdt, oroot_offset, "compatible", | |||||
&ocompat_len) == NULL || ocompat_len == 0) | |||||
return (0); | |||||
root_offset = fdt_path_offset(base_fdt, "/"); | |||||
if (root_offset < 0) | |||||
return (root_offset); | |||||
/* | |||||
* However, an empty or missing /compatible on the base is an error, | |||||
* because allowing this offers no advantages. | |||||
*/ | |||||
if (fdt_get_property(base_fdt, root_offset, "compatible", | |||||
&compat_len) == NULL) | |||||
return (compat_len); | |||||
else if(compat_len == 0) | |||||
return (1); | |||||
slidx = 0; | |||||
compat = fdt_stringlist_get(overlay_fdt, oroot_offset, "compatible", | |||||
slidx, &sllen); | |||||
while (compat != NULL) { | |||||
if (fdt_stringlist_search(base_fdt, root_offset, "compatible", | |||||
compat) >= 0) | |||||
return (0); | |||||
++slidx; | |||||
compat = fdt_stringlist_get(overlay_fdt, oroot_offset, | |||||
"compatible", slidx, &sllen); | |||||
}; | |||||
/* We've exhausted the overlay's /compatible property... no match */ | |||||
return (1); | |||||
} | |||||
void | void | ||||
fdt_apply_overlays() | fdt_apply_overlays() | ||||
{ | { | ||||
struct preloaded_file *fp; | struct preloaded_file *fp; | ||||
size_t max_overlay_size, next_fdtp_size; | size_t max_overlay_size, next_fdtp_size; | ||||
size_t current_fdtp_size; | size_t current_fdtp_size; | ||||
void *current_fdtp; | void *current_fdtp; | ||||
void *new_fdtp; | void *new_fdtp; | ||||
Show All 18 Lines | fdt_apply_overlays() | ||||
overlay = malloc(max_overlay_size); | overlay = malloc(max_overlay_size); | ||||
if (overlay == NULL) { | if (overlay == NULL) { | ||||
printf("failed to allocate memory for DTB blob with overlays\n"); | printf("failed to allocate memory for DTB blob with overlays\n"); | ||||
return; | return; | ||||
} | } | ||||
current_fdtp = fdtp; | current_fdtp = fdtp; | ||||
current_fdtp_size = fdtp_size; | current_fdtp_size = fdtp_size; | ||||
for (fp = file_findfile(NULL, "dtbo"); fp != NULL; fp = fp->f_next) { | for (fp = file_findfile(NULL, "dtbo"); fp != NULL; fp = fp->f_next) { | ||||
COPYOUT(fp->f_addr, overlay, fp->f_size); | |||||
/* Check compatible first to avoid unnecessary allocation */ | |||||
rv = fdt_check_overlay_compatible(current_fdtp, overlay); | |||||
if (rv != 0) { | |||||
printf("DTB overlay '%s' not compatible\n", fp->f_name); | |||||
continue; | |||||
} | |||||
printf("applying DTB overlay '%s'\n", fp->f_name); | printf("applying DTB overlay '%s'\n", fp->f_name); | ||||
next_fdtp_size = current_fdtp_size + fp->f_size; | next_fdtp_size = current_fdtp_size + fp->f_size; | ||||
next_fdtp = malloc(next_fdtp_size); | next_fdtp = malloc(next_fdtp_size); | ||||
if (next_fdtp == NULL) { | if (next_fdtp == NULL) { | ||||
/* | /* | ||||
* Output warning, then move on to applying other | * Output warning, then move on to applying other | ||||
* overlays in case this one is simply too large. | * overlays in case this one is simply too large. | ||||
*/ | */ | ||||
printf("failed to allocate memory for overlay base\n"); | printf("failed to allocate memory for overlay base\n"); | ||||
continue; | continue; | ||||
} | } | ||||
rv = fdt_open_into(current_fdtp, next_fdtp, next_fdtp_size); | rv = fdt_open_into(current_fdtp, next_fdtp, next_fdtp_size); | ||||
if (rv != 0) { | if (rv != 0) { | ||||
free(next_fdtp); | free(next_fdtp); | ||||
printf("failed to open base dtb into overlay base\n"); | printf("failed to open base dtb into overlay base\n"); | ||||
continue; | continue; | ||||
} | } | ||||
COPYOUT(fp->f_addr, overlay, fp->f_size); | |||||
/* Both overlay and new_fdtp may be modified in place */ | /* Both overlay and new_fdtp may be modified in place */ | ||||
rv = fdt_overlay_apply(next_fdtp, overlay); | rv = fdt_overlay_apply(next_fdtp, overlay); | ||||
if (rv == 0) { | if (rv == 0) { | ||||
/* Rotate next -> current */ | /* Rotate next -> current */ | ||||
if (current_fdtp != fdtp) | if (current_fdtp != fdtp) | ||||
free(current_fdtp); | free(current_fdtp); | ||||
current_fdtp = next_fdtp; | current_fdtp = next_fdtp; | ||||
current_fdtp_size = next_fdtp_size; | current_fdtp_size = next_fdtp_size; | ||||
▲ Show 20 Lines • Show All 1,362 Lines • Show Last 20 Lines |