From patchwork Thu Apr 12 12:43:28 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Graeme Russ X-Patchwork-Id: 152053 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 19766B70DA for ; Thu, 12 Apr 2012 22:43:43 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 4A0322809E; Thu, 12 Apr 2012 14:43:41 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id NqctVDwM6UKX; Thu, 12 Apr 2012 14:43:41 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 9B3FF280B1; Thu, 12 Apr 2012 14:43:39 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 9FDC8280B1 for ; Thu, 12 Apr 2012 14:43:37 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Vhhcny6PhrxP for ; Thu, 12 Apr 2012 14:43:36 +0200 (CEST) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mail-pz0-f50.google.com (mail-pz0-f50.google.com [209.85.210.50]) by theia.denx.de (Postfix) with ESMTPS id E22D52809E for ; Thu, 12 Apr 2012 14:43:34 +0200 (CEST) Received: by dakh32 with SMTP id h32so2317994dak.23 for ; Thu, 12 Apr 2012 05:43:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=message-id:date:from:user-agent:mime-version:to:subject :content-type:content-transfer-encoding; bh=6L6WZht8paH+o9rA1Cwf1dUBlewzEY/PPWYL3/dkbzo=; b=OivPOOuoG5x84fCVv9V4J+w/CNjA1XS7XfevlxF9LTNVUZ7nDQc+CDen/+yWUrVOw1 STCmtMr8M5E54s7MZE7vHI9BYu6hNqOcXMyJe/6o8b98pga0P4u0cK9YLGd620qot5P4 U1O5e7Z1zKzAFHM+EsOT5arOm/gjkWnzx2H7Cdhw4D45md17/U5Ju3jPOYZEsknWzFVm ZBcPfdf1OFUgDM0ridf0U/cXrJLP4ofLMyXG4uZR0PDY01cCcvj5rIYxDAAhVAH5EekR 28XwP+IPyRGTCzNJXBk0BmGnakVPONubSQdaYkpIiP9Qn82j+KF0mISSiJp41o1vWlQC VJsQ== Received: by 10.68.225.195 with SMTP id rm3mr2698886pbc.96.1334234612656; Thu, 12 Apr 2012 05:43:32 -0700 (PDT) Received: from dingo.localhost (d175-39-36-1.sbr801.nsw.optusnet.com.au. [175.39.36.1]) by mx.google.com with ESMTPS id q8sm5615626pbi.1.2012.04.12.05.43.30 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 12 Apr 2012 05:43:32 -0700 (PDT) Message-ID: <4F86CDF0.2030208@gmail.com> Date: Thu, 12 Apr 2012 22:43:28 +1000 From: Graeme Russ User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:11.0) Gecko/20120329 Thunderbird/11.0.1 MIME-Version: 1.0 To: U-Boot Users Subject: [U-Boot] [RFC][PATCH] INIT_FUNC - List madness X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de Hello All, This patch is a little heads-up for my upcomming INIT_FUNC patch series This is the INIT_FUNC 'engine' - It processes a file which consists of entries created by the following macros: #define INIT_FUNC(fn, init_name, man_reqs, pre_reqs, post_reqs) \ static const char __init_func_ ## fn[] __used \ __attribute__((__section__(".initfuncs"))) = \ "(f:" #fn ":" #init_name ":" #man_reqs " | " #pre_reqs " | " #post_reqs ")\n"; #define SKIP_INIT(init_name) \ static const char __skip_init_ ## req[] __used \ __attribute__((__section__(".initfuncs"))) = \ "(s:" #init_name ")\n"; #define REPLACE_INIT(old_func, new_func) \ static const char __replace_init_ ## old_func[] __used \ __attribute__((__section__(".initfuncs"))) = \ "(r:" #old_func ":" #new_func ")\n"; So an 'function' entry will look like (f:function_name:init_step:mandatory_req_1 mandatory_req_2 | optional_req_1 optional_req_2 | post_req_1 post_req_2) 'init_step' allows multiple functions to be logically grouped (see below) where: mandatory_req_1 & mandatory_req_2 are functions or 'init steps' which MUST exist and will be put in the init sequence before 'function_name' optional_req_1 & optional_req_2 are functions or 'init steps' which might exist and (if they do) will be put in the init sequence before 'function_name' post_req_1 & post_req_2 are are functions or 'init steps' which might exist and (if they do) will be put in the init sequence after 'function_name' A 'skip' entry will look like: (s:function_or_step_name) The function named 'function_or_step_name' will not be included in the init sequence. If 'function_or_step_name' is the name of a 'step' then all functions which make up that step are skipped - This is to replace a arch-level function (or set of functions) with board specific alternatives. A 'replace' entry will look like: (r:old_name:new_name) Any function named 'old_name' in the init sequence will be replaced with 'new_name' (this is like overriding a weak function without needing to make the function weak) So far this seems to work - It creates a list of functions with each having a list of dependent functions (steps are expanded so the dependency lists only have functions in them) Now I just need to write the code that will order the function list I think this single patch will more than double the use of struct list_head in U-Boot. It took a while to get used to it's sematics, but the Linux kernel list data structure is incredible Regards, Graeme commit 1567e349f774d93e25b3ab2da01cab5e11632916 Author: Graeme Russ Date: Sun Apr 8 22:09:42 2012 +1000 initcall: Some testing diff --git a/tools/mkinitseq.c b/tools/mkinitseq.c new file mode 100644 index 0000000..1e2bbb2 --- /dev/null +++ b/tools/mkinitseq.c @@ -0,0 +1,870 @@ +/* + * (C) Copyright 2012 + * Graeme Russ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/** + * container_of - cast a member of a structure out to the containing structure + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + */ +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) + + +#include "os_support.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef MKINITSEQ_DEBUG + +#ifdef MKINITSEQ_DEBUG +#define debug(fmt,args...) printf (fmt ,##args) +#else +#define debug(fmt,args...) +#endif /* MKINITSEQ_DEBUG */ + +#include + +struct init_id { + struct list_head list; + char *name; +}; + +struct replace_def { + struct list_head list; + char *old_name; + char *new_name; +}; + +struct init_function { + struct list_head list; + + char *function_name; + char *init_step_name; + + struct list_head mandatory_deps; + struct list_head pre_deps; + struct list_head post_deps; +}; + +struct init_step { + struct list_head list; + + char *name; + + struct list_head functions; +}; + +struct list_head init_functions; +struct list_head mandatory_functions; +struct list_head skip_list; +struct list_head replace_list; +struct list_head init_steps; + +/* These are the initialisation sequence placeholders */ +static char default_init_reset[] = "f:RESET:RESET: | | SDRAM"; +static char default_init_sdram[] = "f:SDRAM:SDRAM: RESET | | RELOC"; +static char default_init_reloc[] = "f:RELOC:RELOC: SDRAM | | "; + +static int add_function_to_init_step(struct init_step *init_step, + const char *function_name) +{ + struct init_id *init_id; + + init_id = malloc(sizeof(struct init_id)); + + if (!init_id) + return ENOMEM; + + init_id->name = strdup(function_name); + + if (!init_id->name) { + free(init_id); + return ENOMEM; + } + + list_add(&init_id->list, &init_step->functions); + + return 0; +} + +static int add_init_step_function(const char *init_step_name, + const char *function_name) +{ + int found = 0; + struct list_head *position = NULL ; + struct init_step *init_step = NULL ; + + + list_for_each(position, &init_steps) + { + init_step = list_entry(position, struct init_step, list); + + if (!strcmp(init_step->name, init_step_name)) { + found = 1; + break; + } + } + + if (!found) { + init_step = malloc(sizeof(struct init_step)); + + if (!init_step) + return ENOMEM; + + init_step->name = strdup(init_step_name); + + if (!init_step->name) { + free(init_step); + return ENOMEM; + } + + INIT_LIST_HEAD(&init_step->functions); + list_add(&init_step->list, &init_steps); + } + + return add_function_to_init_step(init_step, function_name); + +} + +static int add_mandatory_init(const char *name) +{ + struct list_head *position = NULL ; + struct init_id *init_id = NULL ; + + list_for_each(position, &mandatory_functions) + { + init_id = list_entry(position, struct init_id, list); + + if (!strcmp(init_id->name, name)) + return 0; + } + + init_id = malloc(sizeof(struct init_id)); + + if (!init_id) + return ENOMEM; + + init_id->name = strdup(name); + + if (!init_id->name) { + free(init_id); + return ENOMEM; + } + + list_add(&init_id->list, &mandatory_functions); + + return 0; +} + +static int process_dep_list(struct list_head *dep_list, char *deps, int mandatory) +{ + int err = 0; + struct init_id *new_init_id; + char *save_ptr; + + char *init_id; + + init_id = strtok_r(deps, " ", &save_ptr); + + while (init_id) { + new_init_id = malloc(sizeof(struct init_id)); + + if (!new_init_id) + return ENOMEM; + + new_init_id->name = strdup(init_id); + + if (!new_init_id->name) { + free(new_init_id); + return ENOMEM; + } + + list_add(&new_init_id->list, dep_list); + + if (mandatory) + if (add_mandatory_init(init_id)) + err = 1; + + init_id = strtok_r(NULL, " ", &save_ptr); + }; + + return err; +} + +static int process_init_info(struct init_function *init_function, char *deps) +{ + char *mandatory_deps; + char *pre_deps; + char *post_deps; + char *save_ptr; + + INIT_LIST_HEAD(&init_function->mandatory_deps); + INIT_LIST_HEAD(&init_function->pre_deps); + INIT_LIST_HEAD(&init_function->post_deps); + + mandatory_deps = strtok_r(deps, "|", &save_ptr); + pre_deps = strtok_r(NULL, "|", &save_ptr); + post_deps = strtok_r(NULL, "|", &save_ptr); + + process_dep_list(&init_function->mandatory_deps, mandatory_deps, 1); + process_dep_list(&init_function->pre_deps, pre_deps, 0); + process_dep_list(&init_function->post_deps, post_deps, 0); + + return 0; +} + +static int check_for_duplicate_function(const char *function_name) +{ + struct list_head *position = NULL; + struct init_function *init_func = NULL; + + list_for_each(position , &init_functions) + { + init_func = list_entry(position, struct init_function, list); + + if (!strcmp(function_name, init_func->function_name)) { + printf("Duplicate init function: %s\n", function_name); + + return EEXIST; + } + } + + return 0; +} + +static int add_to_skip_list(const char *function_name) +{ + struct list_head *position = NULL; + struct init_id *init_id = NULL; + + /* Duplicate skip definitions are OK, but we only want the fist one */ + list_for_each(position , &skip_list) + { + init_id = list_entry(position, struct init_id, list); + + if (!strcmp(function_name, init_id->name)) + return 0; + } + + init_id = malloc(sizeof(struct init_id)); + + if (!init_id) + return ENOMEM; + + init_id->name = strdup(function_name); + + if (!init_id->name) { + free(init_id); + return ENOMEM; + } + + list_add(&init_id->list, &skip_list); + + return 0; +} + +static int add_to_replace_list(const char *old_name, const char *new_name) +{ + struct list_head *position = NULL; + struct replace_def *replace_def = NULL; + + /* Duplicate replace definitions are not OK */ + list_for_each(position , &replace_list) + { + replace_def = list_entry(position, struct replace_def, list); + + if (!strcmp(old_name, replace_def->old_name) || + !strcmp(old_name, replace_def->new_name) || + !strcmp(new_name, replace_def->old_name) || + !strcmp(new_name, replace_def->new_name)) { + printf("Multiple replace definitions for function: %s\n", + old_name); + + return EEXIST; + } + } + + replace_def = malloc(sizeof(struct replace_def)); + + if (!replace_def) + return ENOMEM; + + replace_def->old_name = strdup(old_name); + replace_def->new_name = strdup(new_name); + + if ((!replace_def->old_name) || (!replace_def->new_name)) { + free(replace_def->old_name); + free(replace_def->new_name); + free(replace_def); + return ENOMEM; + } + + list_add(&replace_def->list, &replace_list); + + return 0; +} + +static int process_init_def(char *init_def) +{ + struct init_function *new_init_function; + + char *save_ptr; + char *def_type; + char *function_name; + char *init_step_name; + char *old_name; + char *new_name; + char *deps; + int err; + + def_type = strtok_r(init_def, ":", &save_ptr); + + switch(def_type[0]) { + case 'f': + /* An init function definition - Get the function name */ + function_name = strtok_r(NULL, ":", &save_ptr); + init_step_name = strtok_r(NULL, ":", &save_ptr); + + /* Check that the function is not already included */ + err = check_for_duplicate_function(function_name); + + if (err) + return err; + + err = add_init_step_function(init_step_name, function_name); + + if (err) + return err; + + /* Create a list node for the new init function */ + new_init_function = malloc(sizeof(struct init_function)); + + if (!new_init_function) + return ENOMEM; + + new_init_function->function_name = strdup(function_name); + new_init_function->init_step_name = strdup(init_step_name); + + if ((!new_init_function->function_name) || + (!new_init_function->init_step_name)) { + free(new_init_function->function_name); + free(new_init_function->init_step_name); + free(new_init_function); + return ENOMEM; + } + + /* Add the new function to the init function list */ + list_add(&new_init_function->list, &init_functions); + + /* Process the new functions dependencies */ + deps = strtok_r(NULL, ":", &save_ptr); + return process_init_info(new_init_function, deps); + + break; + + case 's': + function_name = strtok_r(NULL, ":", &save_ptr); + return add_to_skip_list(function_name); + + break; + + case 'r': + old_name = strtok_r(NULL, ":", &save_ptr); + new_name = strtok_r(NULL, ":", &save_ptr); + return add_to_replace_list(old_name, new_name); + + break; + + default: + printf("Unknown Init Type: %s", def_type); + break; + } + + return 0; +} + +static int build_function_list(char *buffer) +{ + int err = 0; + + char *save_ptr; + + char *init_def; + + if (process_init_def(default_init_reset) || + process_init_def(default_init_sdram) || + process_init_def(default_init_reloc)) + err = 1; + + init_def = strtok_r(buffer, "()", &save_ptr); + + while (init_def) { + if (process_init_def(init_def)) + err = 1; + + /* Skip the garbage between init definitions */ + init_def = strtok_r(NULL, "(", &save_ptr); + + /* Get the next init definition */ + init_def = strtok_r(NULL, ")", &save_ptr); + }; + + return err; +} + + +static int open_file(const char *file, char **buffer, int *buf_size) +{ + struct stat sbuf; + int file_ptr; + + char *ptr; + + if ((file_ptr = open(file, O_RDONLY|O_BINARY)) < 0) { + fprintf (stderr, "Can't open %s: %s\n", file, strerror(errno)); + return errno; + } + + if (fstat(file_ptr, &sbuf) < 0) { + fprintf (stderr, "Can't stat %s: %s\n", file, strerror(errno)); + return errno; + } + + ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, file_ptr, 0); + if (ptr == MAP_FAILED) { + fprintf (stderr, "Can't read %s: %s\n", file, strerror(errno)); + return errno; + } + + *buffer = malloc(sbuf.st_size + 1); + + if (!*buffer) + return ENOMEM; + + *buf_size = sbuf.st_size; + memcpy(*buffer, ptr, sbuf.st_size); + (*buffer)[sbuf.st_size] = 0x00; + + munmap((void *)ptr, sbuf.st_size); + close (file_ptr); + + return 0; +} + +static int check_mandatory_list(void) +{ + int err = 0; + struct list_head *position = NULL; + struct list_head *q = NULL; + struct list_head *sub_position = NULL; + struct init_function *init_func = NULL; + struct init_id *init_id = NULL; + + + /* Remove functions that exist from the mandatory functions list */ + list_for_each_safe(position, q, &mandatory_functions) + { + init_id = list_entry(position, struct init_id, list); + + list_for_each(sub_position , &init_functions) + { + init_func = list_entry(sub_position, + struct init_function, + list); + + if (!strcmp(init_id->name, init_func->function_name) || + !strcmp(init_id->name, init_func->init_step_name)) + { + free(init_id->name); + + list_del(position); + free(init_id); + } + } + + } + + list_for_each(position , &mandatory_functions) + { + init_id = list_entry(position, struct init_id, list); + + printf("Missing mandatory function: %s\n", init_id->name); + err = 1; + } + + return err; +} + +static int crosscheck_skip_replace(void) +{ + int err = 0; + + /* + * The same function cannot appear in both the skip list and the + * replace list (either as the new or old function name) + */ + struct list_head *skip_pos = NULL; + struct list_head *replace_pos = NULL; + + struct init_id *skip_def = NULL; + struct replace_def *replace_def = NULL; + + list_for_each(skip_pos, &skip_list) + { + skip_def = list_entry(skip_pos, struct init_id, list); + + list_for_each(replace_pos , &replace_list) + { + replace_def = list_entry(replace_pos, + struct replace_def, + list); + + if (!strcmp(skip_def->name, replace_def->old_name) || + !strcmp(skip_def->name, replace_def->new_name)) + { + printf("Function %s in both skip and replace definitions\n", + skip_def->name); + + err = 1; + } + } + + } + + return err; +} + +static void free_dep_list(struct list_head *dep_list) +{ + struct init_id *tmp; + + while(!list_empty(dep_list)) { + + tmp = list_first_entry(dep_list, struct init_id, list); + + printf("Deleting %s\n", tmp->name); + + free(tmp->name); + list_del(&tmp->list); + } + +} + +static int process_skip_list(void) +{ + int err = 0; + + /* + * The same function cannot appear in both the skip list and the + * replace list (either as the new or old function name) + */ + struct list_head *skip_pos = NULL; + struct init_id *skip_def = NULL; + + struct list_head *func_pos = NULL; + struct list_head *q = NULL; + struct init_function *func_def = NULL; + + list_for_each(skip_pos, &skip_list) + { + skip_def = list_entry(skip_pos, struct init_id, list); + + list_for_each_safe(func_pos, q, &init_functions) { + func_def = list_entry(func_pos, + struct init_function, + list); + + if (!strcmp(func_def->function_name, skip_def->name) || + !strcmp(func_def->init_step_name, skip_def->name)) + { + free(func_def->function_name); + free(func_def->init_step_name); + + free_dep_list(&func_def->mandatory_deps); + free_dep_list(&func_def->post_deps); + free_dep_list(&func_def->pre_deps); + + list_del(func_pos); + + free(func_def); + } + } + } + + return err; +} + +static int process_replace_list(void) +{ + int err = 0; + + /* + * The same function cannot appear in both the skip list and the + * replace list (either as the new or old function name) + */ + struct list_head *func_pos = NULL; + struct list_head *replace_pos = NULL; + + struct init_function *func_def = NULL; + struct replace_def *replace_def = NULL; + + int found; + + list_for_each(replace_pos, &replace_list) + { + replace_def = list_entry(replace_pos, struct replace_def, list); + + found = 0; + + list_for_each(func_pos , &init_functions) + { + func_def = list_entry(func_pos, + struct init_function, + list); + + if (!strcmp(func_def->function_name, + replace_def->old_name)) { + found = 1; + free(func_def->function_name); + func_def->function_name = strdup(replace_def->new_name); + + if (!func_def->function_name) { + printf("strdup() failed!\n"); + err = 1; + } + } + } + if (!found) { + printf("Replace function %s not in init list\n", + replace_def->old_name); + err = 1; + } + } + + return err; +} + +static int insert_into_dep_list(struct list_head *dep_list, + struct init_step *init_step) +{ + struct list_head *position = NULL ; + struct init_id *init_id = NULL ; + struct init_id *new_init_id; + + list_for_each(position, &init_step->functions) + { + init_id = list_entry(position, struct init_id, list); + + new_init_id = malloc(sizeof(struct init_id)); + + if (!new_init_id) + return ENOMEM; + + new_init_id->name = strdup(init_id->name); + + if (!new_init_id->name) { + free(new_init_id); + return ENOMEM; + } + + list_add(&new_init_id->list, dep_list); + } + + return 0; +} + +static int expand_dep_list(struct list_head *dep_list) +{ + int err = 0; + + struct list_head *position = NULL ; + struct init_id *init_id = NULL ; + struct list_head *q = NULL; + + struct list_head *step_pos = NULL ; + struct init_step *init_step = NULL ; + + + list_for_each_safe(position, q, dep_list) { + init_id = list_entry(position, struct init_id, list); + + /* Is this a 'step' rather than a 'function' */ + list_for_each(step_pos, &init_steps) + { + init_step = list_entry(step_pos, + struct init_step, + list); + + if (!strcmp(init_step->name, init_id->name)) { + /* + * Replace this init id (which is a 'step' + * with the list of step functions + */ + free(init_id->name); + + list_del(position); + free(init_id); + + err = insert_into_dep_list(dep_list, + init_step); + + if (err) + return err; + } + } + } + + return 0; +} + +static int expand_dep_lists(void) +{ + int err = 0; + + struct list_head *position = NULL ; + struct init_function *init_func = NULL ; + + list_for_each(position , &init_functions) + { + init_func = list_entry(position, struct init_function, list); + + err = expand_dep_list(&init_func->mandatory_deps); + + if (err) + return err; + + err = expand_dep_list(&init_func->pre_deps); + + if (err) + return err; + + err = expand_dep_list(&init_func->post_deps); + + if (err) + return err; + } + + return 0; +} + +int main(int argc, const char **argv) +{ + int err; + int buf_size; + char *local_buffer = NULL; + char *x; + + INIT_LIST_HEAD(&init_functions); + INIT_LIST_HEAD(&mandatory_functions); + INIT_LIST_HEAD(&skip_list); + INIT_LIST_HEAD(&replace_list); + INIT_LIST_HEAD(&init_steps); + + printf("Generating init sequence from %s\n", argv[1]); + + /* Read the init function definitions into a local buffer */ + err = open_file(argv[1], &local_buffer, &buf_size); + + if(err || !local_buffer) + exit(EXIT_FAILURE); + + /* + * Convert all the NULLs (except the last one) to non-NULL so + * the buffer can be processed using standard string functions + */ + for(x=local_buffer; x != &local_buffer[buf_size]; x++) { + if(*x == 0x00) + *x = 0x01; + } + + if (build_function_list(local_buffer)) + exit(EXIT_FAILURE); + + if (check_mandatory_list()) + exit(EXIT_FAILURE); + + if (crosscheck_skip_replace()) + exit(EXIT_FAILURE); + + if (process_skip_list()) + exit(EXIT_FAILURE); + + if (process_replace_list()) + exit(EXIT_FAILURE); + + if (expand_dep_lists()) + exit(EXIT_FAILURE); + + /* OK - Time to build the init sequence :) */ + + + printf("*** Dumping Lists ***\n"); + + + struct list_head *position = NULL ; + struct init_function *init_func = NULL ; + + struct list_head *sub_position = NULL ; + struct init_id *init_id = NULL ; + + list_for_each(position , &init_functions) + { + init_func = list_entry(position, struct init_function, list); + + printf("Function Name = %s\n", init_func->function_name); + printf("Init Step Name = %s\n", init_func->init_step_name); + + printf(" Mandatory Deps\n"); + list_for_each(sub_position , &init_func->mandatory_deps) + { + init_id = list_entry(sub_position, struct init_id, list); + printf(" - %s\n", init_id->name); + } + + printf(" Pre Deps\n"); + list_for_each(sub_position , &init_func->pre_deps) + { + init_id = list_entry(sub_position, struct init_id, list); + printf(" - %s\n", init_id->name); + } + + printf(" Post Deps\n"); + list_for_each(sub_position , &init_func->post_deps) + { + init_id = list_entry(sub_position, struct init_id, list); + printf(" - %s\n", init_id->name); + } + } + + + free(local_buffer); + exit (EXIT_SUCCESS); +}