diff --git a/fsutils/mkmbr/Kconfig b/fsutils/mkmbr/Kconfig new file mode 100644 index 000000000..7a8403018 --- /dev/null +++ b/fsutils/mkmbr/Kconfig @@ -0,0 +1,11 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +config FSUTILS_MKMBR + bool "mkmbr utility" + default n + select BCH + ---help--- + Enables support for the mkmbr utility diff --git a/fsutils/mkmbr/Make.defs b/fsutils/mkmbr/Make.defs new file mode 100644 index 000000000..89de722cc --- /dev/null +++ b/fsutils/mkmbr/Make.defs @@ -0,0 +1,23 @@ +############################################################################ +# apps/fsutils/mkmbr/Make.defs +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +ifneq ($(CONFIG_FSUTILS_MKMBR),) +CONFIGURED_APPS += $(APPDIR)/fsutils/mkmbr +endif diff --git a/fsutils/mkmbr/Makefile b/fsutils/mkmbr/Makefile new file mode 100644 index 000000000..96abeff1a --- /dev/null +++ b/fsutils/mkmbr/Makefile @@ -0,0 +1,32 @@ +############################################################################ +# apps/fsutils/mkmbr/Make.defs +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +include $(APPDIR)/Make.defs + +# mkmbr built-in application info + +PROGNAME = mkmbr +PRIORITY = 100 +STACKSIZE = $(CONFIG_DEFAULT_TASK_STACKSIZE) +MODULE = $(CONFIG_FSUTILS_MKMBR) + +MAINSRC = mkmbr.c + +include $(APPDIR)/Application.mk diff --git a/fsutils/mkmbr/mkmbr.c b/fsutils/mkmbr/mkmbr.c new file mode 100644 index 000000000..9c0251233 --- /dev/null +++ b/fsutils/mkmbr/mkmbr.c @@ -0,0 +1,188 @@ +/**************************************************************************** + * apps/fsutils/mkmbr/mkmbr.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef FAR +#define FAR +#endif + +#define PACKED __attribute__((packed)) +#define PARTITION_BOOTABLE_FLAG 0x80 +#define PARTITION_TYPE 0x83 /* GNU/Linux */ +#define MBR_BOOT_SIGNATURE 0xAA55 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct PACKED partition_s +{ + uint8_t bootable_flag; + uint8_t first_sector_chs[3]; + uint8_t type; + uint8_t last_sector_chs[3]; + uint32_t first_sector_lba; + uint32_t sectors_num_lba; +}; + +struct PACKED mbr_s +{ + uint8_t bootstrap[446]; + struct partition_s partitions[4]; + uint16_t boot_signature; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const char g_usage[] = "\ +Usage: \n\ +\n\ + mkmbr dev p1_start p1_sectors [p2_start p2_sectors [...]]\n\ +\n\ +Where:\n\ + dev - block device path\n\ + pX_start - first sector number or \"auto\" to use next free sector\n\ + pX_sectors - partition's sectors count or \"auto\" to use all free space\n\ +\n"; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static void print_usage(void) +{ + write(STDERR_FILENO, g_usage, sizeof(g_usage)); +} + +static void mbr_init(FAR struct mbr_s *mbr) +{ + memset(mbr, 0, sizeof(struct mbr_s)); + mbr->boot_signature = MBR_BOOT_SIGNATURE; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int main(int argc, FAR char *argv[]) +{ + unsigned long bsize; + unsigned long start; + unsigned long size; + unsigned long next; + struct mbr_s mbr; + struct stat st; + int partn; + int argn; + int fd; + int ret; + + if (argc < 4 || argc % 2 != 0) + { + print_usage(); + return EINVAL; + } + + fd = open(argv[1], O_RDWR); + if (fd < 0) + { + return errno; + } + + ret = fstat(fd, &st); + if (ret < 0) + { + goto err_exit; + } + + next = 1; + bsize = st.st_size / 512; + mbr_init(&mbr); + for (partn = 0; partn < 4 && next < bsize; partn++) + { + argn = 2 * (partn + 1); + if (!strcmp(argv[argn], "auto")) + { + start = next; + } + else + { + errno = 0; + start = strtoul(argv[argn], NULL, 0); + if (errno) + { + goto err_exit; + } + } + + if (!strcmp(argv[argn + 1], "auto")) + { + size = bsize - start; + } + else + { + errno = 0; + size = strtoul(argv[argn + 1], NULL, 0); + if (errno) + { + goto err_exit; + } + } + + if (start < next || start + size > bsize) + { + errno = EINVAL; + goto err_exit; + } + + mbr.partitions[partn].first_sector_lba = htole32(start); + mbr.partitions[partn].sectors_num_lba = htole32(size); + mbr.partitions[partn].type = PARTITION_TYPE; + next = start + size; + } + + ret = write(fd, &mbr, sizeof(mbr)); + if (ret >= 0) + { + errno = 0; + } + +err_exit: + close(fd); + return errno; +}